Today we're going to build a node.js application to collect email addresses using Kickbox. We'll be using Express and Request on the server side, and jQuery on the client.
We'll be using Glitch during this tutorial, because it provides an environment, editor, and hosting in one convenient package. There's an example of the completed project too. If you want to follow along in your own environment, all of the code will work.
Recipient Authentication makes it easy to collect email addresses the right way. We handle account activation, double email opt-in subscriptions, and password resets. We make sure the email gets delivered, send drip reminders, expire old links, handle opt-outs, and automatically add authenticated addresses to your email service provider or marketing platform.
Our JavaScript library protects your form from bots, spammers and auto-generated signups. And our API integrations make it easy to add the addresses you collect to your email marketing platform.
- A free Kickbox account. Create one here.
- A Kickbox Authentication App Code. Create an authentication app. On the "Connect" page you'll see your app code.
- A Kickbox API key that can access your new authentication app. Hit "Create New Key" on the connect page to create one. Choose "Sandbox" for now.
Keep your App Code and API Key nearby as we'll be using them soon.
Our project today has 3 components. These are:
- A view containing a form to capture an email address and a place to display progress.
- Some client-side JavaScript to fingerprint the client session
- A server-side route to call the kickbox API with the address, fingerprint, and app token
We'll start with some app scaffolding, create the view, add some client code, and wrap things up with the server-side.
Woohoo! To start, fire up a fresh Glitch project. Glitch includes a boilerplate Express app straight away. If you're new to node or express, you might want to take a moment to look around the default code.
The first thing we need to do is add the other npm packages that we'll be using. Click on the package.json
file in the left-hand list to open it. Next, click "Add Package" and add request
and request-promise
to your project. We're also going to use body-parser
to handle API responses, so add that as well.
The entire package.json
file should look like this:
{
"//1": "describes your app and its dependencies",
"//2": "https://docs.npmjs.com/files/package.json",
"//3": "updating this file will download and update your packages",
"name": "my-glitch-app",
"version": "0.0.1",
"description": "What am I about?",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.15.3",
"request-promise": "^4.2.1",
"body-parser": "^1.17.2",
"request": "^2.81.0"
},
"engines": {
"node": "6.10.x"
},
"repository": {
"url": "https://glitch.com/edit/#!/welcome-project"
},
"license": "MIT",
"keywords": [
"node",
"glitch",
"express"
]
}
First things first, open up .env
and add a line with your Kickbox API key. (Don't worry, this file is not public on Glitch).
KICKBOX_KEY=live_613ea0f77aa319317a0ea1ef86b7a60fe036611633ca912f017435d3339125a8
Next, open up server.js
. We're going to start fresh, so delete all the default contents.
First, let's add the dependencies.
var express = require('express');
var request = require('request-promise');
var bodyParser = require('body-parser');
And then let's get our express app ready to go.
//we'll use these later
var api_host = "https://api.kickbox.io/v2/";
var app_code = "YOUR KICKBOX APP CODE HERE";
var app = express(); //create a new express app
app.use(bodyParser.urlencoded({extended: false})); //use body-parser for JSON
app.use(express.static('public')); //use the 'public' folder for css, js, images...
var listener = app.listen(process.env.PORT, function () {
console.log('Your app is listening on port ' + listener.address().port);
});
Now let's head over to views/index.html
. This is where we're going to add our email capture form and a container for our progress tracker.
<form>
<h1>Sign Up</h1>
<h2>Fill out the form below to get started.</h2>
<label for="email">Email Address</label>
<input required type="email" name="email"/>
<br/><br/>
<button type="submit">
Submit
</button>
</form>
<div id="tracker"></div>
And we are going to add one additional required client-side script file. This file generates a fingerprint, allowing Kickbox to differentiate between legitimate users and malicious users (bulk account creators, bots, spammers, etc).
<script type="text/javascript" src="https://kickbox.io/authenticate/1/release.js"></script>
The entire views/index.html
file should look like this:
<!DOCTYPE html>
<html>
<head>
<title>Kickbox Email Capture Demo</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<form>
<h1>Sign Up</h1>
<h2>Fill out the form below to get started.</h2>
<label for="email">Email Address</label>
<input required type="email" name="email"/>
<br/><br/>
<button type="submit">
Submit
</button>
</form>
<div id="tracker"></div>
<script src="https://code.jquery.com/jquery-2.2.1.min.js"
integrity="sha256-gvQgAFzTH6trSrAWoH1iPo9Xc96QxSZ3feW6kem+O00="
crossorigin="anonymous"></script>
<script src="https://kickbox.io/authenticate/1/release.js"></script>
<script src="/client.js"></script>
</body>
</html>
Now that we've got an index.html
view with an email capture form, we need to tell our app how to serve it via routing.
Let's open server.js
again. Before the var listener=...
line, we're going to define our first route.
app.get("/", function (request, response) {
response.sendFile(__dirname + '/views/index.html');
});
Now click the Show Live button in your project. You should see the rendered index.html
view with the email capture form.
Now let's make that form do some stuff. Open up public/client.js
and clear out contents of the existing function.
Our client side code will do four things.
- Handle the form's
submit
event. - Generate a fingerprint from the provided email address.
- Send the data to our server-side code
- Show the Kickbox email tracker
Let's get #1 sorted out first.
$(function() {
//Your Recipient Authentication auth code
var kickbox_app_code = "YOUR KICKBOX APP CODE";
var email;
$('form').submit(function(event) {
//only prevent the default submit action if the form is valid
//otherwise, let it proceed and fail, so we get native HTML5 validation
if(self.form[0].checkValidity()) {
event.preventDefault();
}
//get the provided email address
email = $('input').val();
//get the fingerprint, call our server-code, display tracker
Kickbox.fingerprint(
{
app: kickbox_app_code, //your kickbox authentication app code
email: email, // Email address to authenticate
onSuccess: fingerprintSuccess,
onError: function(err) {
alert(err);
}
});
});
});
Let's jump over to the server-side and revisit the client-side later.
We need to define a route to handle the request from the client-side code and then use the provided email address and fingerprint to call the Kickbox API.
Let's go back to server.js
and define another route. This time, we'll be handling a POST request to the /authenticate
route.
app.post("/authenticate", (req, response) => {
var email = req.body.email;
var kickbox_app_code = req.body.kickbox_app_code;
var fingerprint = req.body.fingerprint;
//once defined, this method will return our API call options
var kickbox_call = getKickboxCall(req.body.email, req.body.fingerprint, req.body.kickbox_app_code);
// make the call and handle any errors
// after the request is done, send the API response directly to the client (even if it errors)
request(kickbox_call).then(function(result){
response.send(result);
}).catch(function(err){
response.send(err.response);
});
});
Our route is created. Now let's define that getKickboxCall
that generates the necessary options we need to pass to request-promise.
var getKickboxCall = function(email, fingerprint, kickbox_app_code)
{
var kickboxCall = {
uri: api_host + "authenticate" + "/" + kickbox_app_code,
method: "POST",
form: {
apikey: process.env.KICKBOX_KEY,
email: email,
fingerprint: fingerprint
},
json: true
};
return kickboxCall;
}
Nice work, the server-side is good to go! Let's take a look at the whole server.js
file:
var express = require('express');
var request = require('request-promise');
var bodyParser = require('body-parser');
//we'll use these later
var api_host = "https://api.kickbox.io/v2/";
var app_code = "YOUR KICKBOX APP CODE HERE";
var app = express(); //create a new express app
app.use(bodyParser.urlencoded({extended: false})); //use body-parser for JSON
app.use(express.static('public')); //use the 'public' folder for css, js, images...
app.get("/", function (request, response) {
response.sendFile(__dirname + '/views/index.html');
});
app.post("/authenticate", (req, response) => {
var email = req.body.email;
var kickbox_app_code = req.body.kickbox_app_code;
var fingerprint = req.body.fingerprint;
//once defined, this method will return our API call options
var kickbox_call = getKickboxCall(req.body.email, req.body.fingerprint, req.body.kickbox_app_code);
// make the call and handle any errors
// after the request is done, send the API response directly to the client (even if it errors)
request(kickbox_call).then(function(result){
response.send(result);
}).catch(function(err){
response.send(err.response);
});
});
var getKickboxCall = function(email, fingerprint, kickbox_app_code)
{
var kickboxCall = {
uri: api_host + "authenticate" + "/" + kickbox_app_code,
method: "POST",
form: {
apikey: process.env.KICKBOX_KEY,
email: email,
fingerprint: fingerprint
},
json: true
};
return kickboxCall;
}
var listener = app.listen(process.env.PORT, function () {
console.log('Your app is listening on port ' + listener.address().port);
});
Let's jump back over to client.js
and finish up.
We need to generate a fingerprint and send it to Kickbox. The Kickbox.fingerprint()
call requires three things: an email, an app code, and an onSuccess
callback function.
Our onSuccess
callback is going to POST to the /authenticate
route we created in server.js
. Let's write that now.
var fingerprintSuccess = function(fingerprint) {
//make a post to our /authenticate route
$.post( "/authenticate",
{
email: email,
fingerprint: fingerprint,
kickbox_app_code: kickbox_app_code
},
//handle the response
function(response){
//do this if something goes wrong
if (response.success != true) {
alert(response.body.message);
return;
}
//get the tracking token from the API response
var track_token = response.track_token;
//show the kickbox email tracker
Kickbox.track({
app: kickbox_app_code,
token: track_token,
element: $('#tracker')[0]
});
});
}
We're almost there. Let's go to our form submit
handler and remove the TODO
.
//Your Recipient Authentication auth code
var kickbox_app_code = "YOUR KICKBOX APP CODE";
$('form').submit(function(event) {
//prevent default form submission handler
event.preventDefault();
//get the provided email address
var email = $('input').val();
Kickbox.fingerprint({
app: kickbox_app_code, //your kickbox authentication app code
email: email, // Email address to authenticate
onSuccess: fingerprintSuccess,
onError: function(err) {
alert(err);
}
});
}
And that's it for the client side. The completed public/client.js
file should look similar to this:
$(function() {
var email;
//Your Recipient Authentication auth code
var kickbox_app_code = "YOUR KICKBOX APP CODE";
$('form').submit(function(event) {
//prevent default form submission handler
event.preventDefault();
//get the provided email address
email = $('input').val();
//get the fingerprint, call our server-code, display tracker
Kickbox.fingerprint(
{
app: kickbox_app_code, //your kickbox authentication app code
email: email, // Email address to authenticate
onSuccess: fingerprintSuccess,
onError: function(err) {
alert(err);
}
});
});
var fingerprintSuccess = function(fingerprint) {
//make a post to our /authenticate route
$.post( "/authenticate",
{
email: email,
fingerprint: fingerprint,
kickbox_app_code: kickbox_app_code
},
//handle the response
function(response){
//do this if something goes wrong
if (response.success != true) {
alert(response.body.message);
return;
}
//get the tracking token from the API response
var track_token = response.track_token;
//show the kickbox email tracker
Kickbox.track({
app: kickbox_app_code,
token: track_token,
element: $('#tracker')[0]
});
});
}
});
We're done! Click "Show Live." Fill out the form with an email address you control, then watch the tracker as you move through the authentication process.
You will also see some activity show up on your Authentication dashboard.
Now that you've got the basics working, there are several ways to handle authentication status. You can respond programmatically to new authentication events via webhook or redirect the user to a page of your choosing after authentication. And there's an API endpoint for retrieving authentication status.
Want to automatically add the emails you collect to a list on your email service provider's platform? Go to the advanced settings sections of your Authentication app and click "Mailing Lists."
And in the Advanced Settings section of the website, you can configure drip reminders and link expiration.
If you got any questions or comments, please get in touch! We're here to help.