Verify User Addresses via Postcard With Lob + Mandrill + Hapi

755
Lob
The simplest way to integrate printing into your applications.

By Russell Taylor, Growth Engineer, at Lob.


Here at Lob we specialize in print and mail. More specifically, we have built an API that provides a RESTful interface for printing and mailing postcards, letters, checks, photos, and more. Over the years we’ve seen all sorts of creative implementations of our APIs, but one use case we keep seeing is the need for companies to verify a user's physical mailing address.

Companies like Couchsurfing, Google Local, and Yelp have all solved this problem by sending address verification postcards to users that contain individualized activation codes. Several of our own customers are doing this and we are excited to share a simple solution that utilizes our Postcard Printing API, the Mandrill Email API, and the hapi Node.js web server.

In this tutorial we are going to walk you through how to setup a user registration form that will send a confirmation email and a postcard that contains a validation code. After a user receives the postcard, they will visit the website on the postcard and enter the validation code to confirm their mailing address.

This is not an exhaustive tutorial since we will not be persisting any data. Instead I hope to show you a basic skeleton that you can use in your own Node.js project and extend to meet your needs.

Contents



Before you start

  • You will need to head over to Lob and Mandrill to register for test API keys.
  • I’m assuming you are somewhat familiar with JavaScript and Node.js. You don’t need to be an expert, but it will be advantageous if you have used server side JavaScript before.
  • I’ll be using the the Bluebird promise library to chain together asynchronous API calls. If you aren’t familiar with promises, I suggest a little light reading before getting started.
  • This project’s source code is available on GitHub. Just clone the repository and follow the instructions in the README.md to get started. It is a good idea to get the project running locally so you can reference it during the tutorial.

Quick Preview

Here is a screenshot of the Lob dashboard and the postcard we will be sending out to users as they sign up:


Lob Postcard Dashboard


Project Structure

This whole project will live inside the hapi framework. Hapi is minimalistic Node.js framework that favors configuration over code. All the functionality of the project will live inside the plugin called lob-registration-postcard which will utilize two reusable services called email.js and lob.js. Again, make sure to check out the GitHub repository to download and run the full project.

Here is what the src folder of our project looks like:


Hapi node.js src folder


Main server.js File

This is our main application file. It serves to include the necessary plugins and services, as well as create the server connection.

'use strict';

var Hapi = require('hapi');
var server = new Hapi.Server();

server.register([
  require('./services/config'),
  require('./services/lob'),
  require('./services/email')
], function (err) {
  if (err) {
    throw err;
  }
});

server.connection({
    port: server.plugins.config.port,
    labels: ['http']
});

server.views({
  engines: {
    hbs: require('handlebars')
  },
  relativeTo: __dirname,
  path: './views',
  layoutPath: './views/layouts',
  layout: 'defaultLayout'
});

server.register([
  require('./plugins/lob-registration-postcard')
], function (err) {
  if (err) {
    throw err;
  }
});

server.start();
console.log('Server Started on:', server.info.uri);

Notice that one of the registered services is require('./services/config'). Take a peek at this directory and you will notice a development.json file which contains some of our configuration variables for the project. This includes a default FROM address and our API keys.

Once you have signed up for your Lob and Mandrill API keys, go ahead and plug them in here.

{
  "port": 3000,
  "lob_api_key": "XXX",
  "mandrill_api_key": "XXX"
  "fromAddress": {
    "name": "Lob",
    "email": "joe@example.com",
    "address_line1": "185 Berry",
    "address_line2": "Suite 1851",
    "address_city": "San Francisco",
    "address_state": "CA",
    "address_zip": "94117",
    "address_country": "US"
  }
}

The Services

For the purposes of this tutorial, I’ll be organizing our code into two categories, Services and Plugins. Services will be used to create wrappers around both the Lob and Mandrill APIs. It’s completely possible to use both these APIs right inside our main plugin, but by creating services we can easily reuse their functionality across the project.

Configure email sending via Mandrill

The main goal of the email.js service will be to provide a single sendEmail() function that will accept a FROM and TO address as parameters. The strategy here is to abstract away all the logic that builds and sends a message, so that when we call sendEmail() we will be returned a promise that can be used in a promise chain.

Here is the complete code for email.js which I’ll explain in detail below:

var Bluebird = require('bluebird');

exports.register = function (server, options, next) {

  var mandrill         = require('mandrill-api/mandrill');
  var mandrill_client  = new mandrill.Mandrill(server.plugins.config.mandrill_api_key);

  var send = function (message) {
    return new Bluebird(function (resolve, reject) {
      mandrill_client.messages.send({
        message: message,
        async: false
      }, function (result) {
        return resolve(result);
      }, function (e) {
        return reject(e);
      });
    });
  };

  var buildEmailMessage = function (toAddress) {
    var msg = '<p>Hey ' + toAddress.name + ',</p>';
    msg += '<p>We are happy you have decided to user our service. ';
    msg += 'An address verification postcard has been sent to:</p>';
    msg += '<p>' + toAddress.name + '</p>';
    msg += '<p>' + toAddress.address_line1 + '</p>';
    msg += '<p>' + toAddress.address_city + ', ';
    msg += toAddress.address_state + ', ';
    msg += toAddress.address_zip + '</p>';
    msg += '<p>When you receive the postcard, follow the instruction on the card to verify your home address</p>';
    msg += '<p>-- The Team</p>';
    return msg;
  }

  var sendEmail = function sendEmail (fromAddress, toAddress) {

    var message = {
        'html': buildEmailMessage(toAddress),
        'subject': 'Welcome to the Club!',
        'from_email': fromAddress.email,
        'from_name': fromAddress.name,
        'to': [{
                'email': toAddress.email,
                'name': toAddress.name,
                'type': 'to'
            }],
        };

    return send(message);
  }

  server.expose('sendEmail', sendEmail);
  next();
};

exports.register.attributes = {
  name: 'email',
};

At the top of the service we need to include and initialize the Mandrill API. Notice that we are pulling in our API key from the config file I mentioned earlier and passing it as an argument.

var mandrill = require('mandrill-api/mandrill');
var mandrill_client = new mandrill.Mandrill(server.plugins.config.mandrill_api_key);

If you take a look at the var send = function (message){} function you will notice that we need to do a little extra work here because the Mandrill API does not automatically return a promise when calling the send function. In this situation we can use Bluebird to wrap the Mandrill API callback in a promise.

Now we are ready to write the sendEmail() function, which will be called once the user has successfully registered. All we need to do is build the message JSON as specified by the Mandrill Message Docs and then return our promisified send() function.

var message = {
    'html': buildEmailMessage(toAddress),
    'subject': 'Welcome to the Club!',
    'from_email': fromAddress.email,
    'from_name': fromAddress.name,
    'to': [{
        'email': toAddress.email,
        'name': toAddress.name,
        'type': 'to'
    }],
};
return send(message);

The last thing we need to do is expose our sendEmail() function so that we can call it from inside our plugin.

server.expose('sendEmail', sendEmail);

Configure postcard sending via Lob

As with the email service, the main purpose of the lob.js service will be to expose the necessary API endpoints for use in our plugin. The lob API natively returns promises for each call, which means we won’t need to wrap anything using Bluebird.

Here is the complete code for the service, which I’ll break out for explanation below:

var randomstring  = require("randomstring");

exports.register = function (server, options, next) {

  var Lob = require('lob')(server.plugins.config.lob_api_key);

  var verifyAddress = function (payload) {
    return Lob.verification.verify({
      address_line1: payload.address,
      address_city: payload.city,
      address_state: payload.state,
      address_zip: payload.zip,
      address_country: 'US',
    });
  }

  var createAddress = function (payload , verifiedAddress) {
    return Lob.addresses.create({
      description: 'User ' + payload.name + '\'s Address',
      name: payload.name,
      email: payload.email,
      address_line1: verifiedAddress.address_line1,
      address_city: verifiedAddress.address_city,
      address_state: verifiedAddress.address_state,
      address_zip: verifiedAddress.address_zip,
      address_country: verifiedAddress.address_country
    });
  }

  var createPostcard = function (toAddress, postcardFront) {
    return Lob.postcards.create({
      description: 'Registration Postcard for ' + toAddress.name,
      to: toAddress.id,
      from: server.plugins.config.fromAddress,
      front: postcardFront,
      message: 'Welcome to the club!',
      data: {
        activate_code: randomstring.generate(5)
      }
    });
  }


  server.expose('createPostcard', createPostcard);
  server.expose('createAddress', createAddress);
  server.expose('verifyAddress', verifyAddress);

  next();
};

exports.register.attributes = {
  name: 'lob',
};

The first thing we need to do is load the Lob API. As with the email.js service we are including our API key from the config file.

var Lob = require('lob')(server.plugins.config.lob_api_key);

The first Lob functionality we want to expose is the address verification API. When a user registers and provides a mailing address we want to make sure it’s a valid address before sending them a postcard, otherwise we should prompt them with an error message.

var verifyAddress = function (payload) {
   return Lob.verification.verify({
      address_line1: payload.address,
      address_city: payload.city,
      address_state: payload.state,
      address_zip: payload.zip,
      address_country: 'US',
   });
}

The payload parameter is just the result of the user submitted form that we will go over in a minute. Make sure to check out the address verification docs for a full explanation of the address verification endpoint.

Note: I’m assuming mailing addresses are domestic by hardcoding the country as US. Make sure to update this field if you provide a country option in your registration form.

Once we know a user submitted mailing address is valid, we will need to create the address using the Lob.addresses.create endpoint. Take a look at the address create docs for a full description of the fields.

var createAddress = function (payload , verifiedAddress) {
  return Lob.addresses.create({
      description: 'User ' + payload.name + '\'s Address',
      name: payload.name,
      email: payload.email,
      address_line1: verifiedAddress.address_line1,
      address_city: verifiedAddress.address_city,
      address_state: verifiedAddress.address_state,
      address_zip: verifiedAddress.address_zip,
      address_country: verifiedAddress.address_country
  });
}

Finally, in order to print and mail postcards, we need to expose the postcard create endpoint.

 var createPostcard = function (toAddress, postcardFront) {
    return Lob.postcards.create({
      description: 'Registration Postcard for ' + toAddress.name,
      to: toAddress.id,
      from: server.plugins.config.fromAddress,
      front: postcardFront,
      message: 'Welcome to the club!',
      data: {
        activate_code: randomstring.generate(5)
      }
   });
}

This is the core of the tutorial so lets break down each field for a closer look. Make sure to check out the postcard api documentation for full descriptions and additional options:

  • description: a meta field to help find and organize postcard requests.
  • to: accepts the ID of the address created with our createAddress()function.
  • from: we are just passing the default FROM address from our config file.
  • front: HTML template design for the front of the postcard.
  • message: text that will be displayed on the back of the postcard.
  • data: variables to pass to our postcard template file.

Notice that we are passing an activation code variable in the data field. For the purposes of this tutorial I’m just generating a random string. In a real world example you will need to store each activation code so that the user can confirm it later.

And last but not least, we need to expose these three functions.

server.expose('createPostcard', createPostcard);
server.expose('createAddress', createAddress);
server.expose('verifyAddress', verifyAddress);

Wire up registration form and sending with Hapi

Now that our services are in place we turn our attention to the plugin. Here is the hapi definition of a plugin:

hapi has an extensive and powerful plugin system that allows you to very easily break your application up into isolated pieces of business logic, and reusable utilities.

We will use the lob-registration-postcard plugin to define our routes and business logic for when a user submits the registration form. The first thing we need to do is include the services that we just wrote so that we have access to the Lob and Mandrill APIs.

var Lob = server.plugins.lob;
var Email = server.plugins.email;

Next, lets take a look at the registration form. The route configuration is pretty simple for this one. We are just letting Hapi know that when someone does a GET request on the root url, that we need to render the the home view.

server.route([{
  method: 'GET',
  path: '/',
  config: {
    handler: function (request, reply) {
    reply.view('lob-registration-postcard/home');
  }
}

Here's what the form looks like:


Address Verification Registration Form


If you open up the /src/views/lob-registration-postcard/home.hbs file you will see the HTML used to generate the registration form. This is just basic HTML, but take note that we are posting the form back to the root url.

<form action="/" method="POST" class="form">

Now we are ready to pull all our hard work together and write the logic for when a user submits the registration form. Here is the code in full, I’ll walk you through each step below:

method: 'POST',
path: '/',
config: {
  handler: function (request, reply) {
    readFile( __dirname + '/postcard_template.html', 'utf8')
    .bind({})
    .then(function (templateFile) {
      this.postcardFront = templateFile;
      return Lob.verifyAddress(request.payload)
    })
    .then(function (verifiedAddress) {
      return Lob.createAddress(request.payload, verifiedAddress.address);
    })
    .then(function (toAddress) {
      this.toAddress = toAddress;
      return Lob.createPostcard(this.toAddress, this.postcardFront);
    })
    .then(function (postcard) {
      this.postcard = postcard;
      return Email.sendEmail(
        server.plugins.config.fromAddress,
        this.toAddress
      );
    })
    .then(function (mail) {
      reply.view('lob-registration-postcard/success');
    })
    .catch(function (error) {
      reply(error);
    });
}

The first step in our promise chain is to read in the postcard template file.

readFile( __dirname + '/postcard_template.html', 'utf8')

Here is a screenshot of the postcard we will be sending out to users as they sign up:


Address Verification Postcard


If you open up the /postcard_template.html you will find the basic HTML and CSS for our postcard design. I’ve omitted the CSS, but take a look at the HTML and note the template variable used for the activation code, {{activate_code}}.

  <body>
    <div id="safe-area">
      <div class="text">
        <h1>Welcome to the Club!</h1>
        <p>To verify your address, visit www.example.com/verify and use the activation code below.</p>
      </div>
      <div class="activation-code">
        {{activate_code}}
      </div>
    </div>
  </body>

The Lob Postcard API can also accept PDF, JPEG, and PNG files for postcard designs, but by using HTML we have the ability to define variables in the template file that can be replaced with unique values. This is how we will dynamically assign an activation code to each user as they register. The syntax for template variables look like this: {{variable_name}}

The next step in the promise chain is to verify the mailing address submitted by the user. All we need to do is pass the data from our form submission (request.payload) to the verifyAddress() function we built earlier.

.then(function (templateFile) {
   this.postcardFront = templateFile;
   return Lob.verifyAddress(request.payload)
})

If the address passes validation, we create it and then pass it to the Lob.createPostcard() function along with the HTML file for the front of the postcard.

.then(function (verifiedAddress) {
   return Lob.createAddress(request.payload, verifiedAddress.address);
})
.then(function (toAddress) {
  this.toAddress = toAddress;
  return Lob.createPostcard(this.toAddress, this.postcardFront);
 })

And finally, once the postcard has been successfully created, we send the user an email and then reply with a success message.

.then(function (postcard) {
   this.postcard = postcard;
   return Email.sendEmail(
     server.plugins.config.fromAddress,
     this.toAddress
   );
})
.then(function (mail) {
   reply.view('lob-registration-postcard/success');
})

Testing

So, by this point you should have all the pieces in place and be ready to test. Go ahead and submit your registration form with some test data, making sure to use an email you have access to. If everything works as expected you should be redirected to the success page after submitting the form. If not, you will probably see some errors printed to the screen.

Now, two things should happen: you should receive an email and you should be able to see your postcard in the Lob Dashboard. If you are logged into the Lob Dashboard click the Postcards tab to see recent activity. If your postcard is there click it and you should see a preview/details page like this:

Lob Postcard Dashboard

Final Thoughts

Hopefully you are at a point where you can start extending this example to fit your specific needs. If you have any questions about the tutorial or Lob services, don't hesitate to drop us a line.

Lob
The simplest way to integrate printing into your applications.
Tools mentioned in article
Open jobs at Lob
Senior Software Engineer - Personaliz...
United States
<div class="content-intro"><p><span style="font-weight: 300;">Lob was built by technical co-founders with a vision to make the world programmable.</span></p> <p><span style="font-weight: 300;">We offer two flagship APIs (print &amp; mail and address verification) that enable companies to send postal mail as effortlessly as sending emails. Lob is venture-backed by some of the most reputable investors in tech, and we are building our team to shape the future of our company and meet the demands of a quickly growing customer base and dynamic product offerings.&nbsp;</span></p> <p><span style="font-weight: 300;">As a proud Pledge 1% company, we’re committed to leveraging our product, partnerships, and people to drive positive social impact through </span><a href="http://www.lob.org"><em><span style="font-weight: 300;">Lob.org</span></em></a><span style="font-weight: 300;">, and are on a mission to make direct mail more sustainable.</span></p></div><p><strong>Senior Full Stack Software Engineer - Personalization&nbsp;</strong></p> <p>The Personalization team transforms at scale a variety of customer inputs into a cohesive, professional PDF file suitable for printing by a variety of printing partners. We enable our customers to create the mail they want to see delivered, without requiring professional tooling to do it.&nbsp;</p> <p>We work mainly with Node.js, Vue.js along with a smattering of C++. All of our services run on AWS, with a Service Oriented Architecture.&nbsp; We connect SQS queues to Lambda processes and container workloads, creating a lightning fast pipeline delivering our rendering artifacts.&nbsp; We maintain a culture of high collaboration, psychological safety and performance where individuals can thrive and do the best work of their careers.</p> <p><strong>As the Senior Software Engineer, you’ll…</strong></p> <ul> <li>Collaborate closely with the Product team and other stakeholders to help implement new features and services</li> <li>Work on both front-end UIs and backend systems&nbsp;</li> <li>Be responsible for leading projects from design to implementation</li> <li>Learn and champion best practices in code design and architecture</li> <li>Coach and mentor fellow engineers and team members</li> <li>Work with our Engineering leadership to support and grow the culture of our engineering team</li> </ul> <p><strong>What will you bring to this role…</strong></p> <ul> <li>4+ years of experience in Javascript, preferably Node.js and/or Typescript.&nbsp;&nbsp;</li> <li>3+ years in roles involving operational responsibility for large-scale software systems (monitoring, alerting, production debugging, etc.). While we ultimately value expertise over experience, we expect that a successful candidate for this role will have 4+ years working with complex production systems.</li> <li>2+ years in formal or informal leadership roles that involve significant time mentoring and teaching co-workers about software best practices.</li> <li>Full stack engineering background, you are comfortable writing backend code and creating front-end UIs (we use Vue)</li> <li>Empathy and effective communication skills: you can advocate for teammates and stakeholders such as customers and product managers;&nbsp; you can explain complex technical issues to audiences of diverse technical understanding.</li> <li>Production experience with job-queueing systems, containers (Docker), and AWS services (SQS, S3, ECS)</li> </ul> <p><strong>At Lob, we are looking to #LevelUp and #EmpowerDiversity, we invite you to apply if you possess even some of these:</strong></p> <ul> <li>Ability to design and vet micro-service and cloud-based architectures at scale, as well as support your teammates in doing the same.</li> <li>Effective project management skills: track record of working together with product managers to bring projects from inception to completion.</li> </ul> <p><strong>Compensation information</strong></p> <p><strong>CA/NYC Tier:</strong></p> <p>Base: $170,000 - $178,500</p> <p><strong>US Tier:</strong></p> <p>Base: $160,000 - $168,500</p> <p>&nbsp;</p> <p><span style="color: white;">&lt;#LI-REMOTE #LI-GD1</span></p><div class="content-conclusion"><p><span style="font-weight: 300;">“Lob’s salary ranges are based on market data, relative to our size, industry and stage of growth. Salary is one part of total compensation, which also includes equity, perks and competitive benefits. Salary decisions are based on many factors including geographic location, qualifications for the role, skillset, proficiency and experience level. Lob reasonably expects to pay candidates who are offered roles within the provided salary ranges.”</span></p> <p><span style="font-weight: 300;">We offer remote working opportunities in AZ, CA, CO, DC, FL, GA, IA, IL, MA, MD, MI, MN, NE, NC, NH, NJ, NV, NY, OH, OR, PA, RI, TN, TX, UT, and WA,&nbsp;<span style="text-decoration: underline;"><strong>unless specified otherwise in the job description above.&nbsp;</strong></span></span></p> <p><span style="font-weight: 300;">If you are looking for a progressive, fun-spirited, and mentally stimulating environment, come join us at Lob!</span></p> <p>&nbsp;</p> <p><span style="color: #000000;"><strong>Our Commitment to Diversity</strong></span></p> <p><span style="color: #000000;"><span style="font-weight: 300;">Lob is an equal opportunity employer and </span><a style="color: #000000;" href="https://www.lob.com/blog/power-diversity-starts-data"><em><span style="font-weight: 300;">values diversity</span></em></a><span style="font-weight: 300;"> of </span><a style="color: #000000;" href="https://www.lob.com/blog/a-commitment-to-diversity"><em><span style="font-weight: 300;">backgrounds and perspectives</span></em></a><span style="font-weight: 300;"> to cultivate an environment of understanding to have greater impact on our business and customers. We encourage under-represented groups to apply and do not discriminate on the basis of race, religion, color, national origin, gender, sexual orientation, age, marital status, veteran status, disability status, or criminal history in accordance with local, state, and/or federal laws, including the </span><a style="color: #000000;" href="https://sfgov.org/olse/sites/default/files/Document/FCO%20Art.%2049%20Official%20Notice%20to%20print%202017.pdf"><em><span style="font-weight: 300;">San Francisco’s Fair Chance Ordinance</span></em></a><span style="font-weight: 300;">.</span></span></p> <p><span style="color: #000000;"><strong>Recent awards</strong></span></p> <p><span style="color: #000000;"><span style="font-weight: 300;"><img src="https://keep.google.com/u/0/media/v2/1e8T9oEtvbqRcrMcmtMSXLguNCPTDvK9fgYyRHPMut1prD3B1tXfjRFr3o2O1dlQ/1mas8D_M3MtQ6MJEDfG-6yRUXNoeICQQ-q7BzV0N3BOFVMtPtiGQm3VTYWAtzlnE?sz=512&amp;accept=image%2Fgif%2Cimage%2Fjpeg%2Cimage%2Fjpg%2Cimage%2Fpng%2Cimage%2Fwebp" alt="" width="NaN" height="NaN">BuiltIn Best Midsize Companies to Work For 2022</span><span style="font-weight: 300;"><br></span><span style="font-weight: 300;">#86 on Y Combinator's Top Private Companies List 2021</span><span style="font-weight: 300;"><br></span><span style="font-weight: 300;">BuiltIn Best Midsize Companies to Work For 2021</span><span style="font-weight: 300;"><br></span><span style="font-weight: 300;">2020 Inc 5000 List of the Fastest-Growing Private Companies</span><span style="font-weight: 300;"><br></span><span style="font-weight: 300;">2019 Timmy Awards - Best Tech Workplace for Diversity, Community Favorite in the Bay Area</span><span style="font-weight: 300;"><br></span><span style="font-weight: 300;">Deloitte’s 2019 Technology Fast 500<br><br></span></span></p></div>
Senior Software Engineer
United States
<div class="content-intro"><p><span style="font-weight: 300;">Lob was built by technical co-founders with a vision to make the world programmable.</span></p> <p><span style="font-weight: 300;">We offer two flagship APIs (print &amp; mail and address verification) that enable companies to send postal mail as effortlessly as sending emails. Lob is venture-backed by some of the most reputable investors in tech, and we are building our team to shape the future of our company and meet the demands of a quickly growing customer base and dynamic product offerings.&nbsp;</span></p> <p><span style="font-weight: 300;">As a proud Pledge 1% company, we’re committed to leveraging our product, partnerships, and people to drive positive social impact through </span><a href="http://www.lob.org"><em><span style="font-weight: 300;">Lob.org</span></em></a><span style="font-weight: 300;">, and are on a mission to make direct mail more sustainable.</span></p></div><p><strong>Senior Software Engineer</strong></p> <p>Lob was built by technical co-founders with a vision to make the world programmable.</p> <p>We offer two flagship APIs (print &amp; mail and address verification) that enable companies to send postal mail as effortlessly as sending emails. Lob is venture-backed by some of the most reputable investors in tech, and we are building our team to shape the future of our company and meet the demands of a quickly growing customer base and dynamic product offerings.&nbsp;</p> <p><strong>Senior Full Stack Software Engineer </strong></p> <p>As a Senior Software Engineer at Lob, you’ll have the ability to handle various parts of Lob’s operational stack. We work mainly with Node.js, Typescript, and Vue.js. All of our services run on AWS, with a Service Oriented Architecture.&nbsp; We connect SQS queues to Lambda processes and container workloads.&nbsp; We maintain a culture of high collaboration, psychological safety and performance where individuals can thrive and do the best work of their careers.</p> <p>&nbsp;</p> <p><strong>As the Senior Software Engineer, you’ll…</strong></p> <ul> <li>Collaborate closely with the Product team and other stakeholders to help implement new features and services</li> <li>Work on both front-end UIs and backend systems&nbsp;</li> <li>Be responsible for leading projects from design to implementation</li> <li>Learn and champion best practices in code design and architecture</li> <li>Coach and mentor fellow engineers and team members</li> <li>Work with our Engineering leadership to support and grow the culture of our engineering team</li> </ul> <p><strong>What will you bring to this role…</strong></p> <ul> <li>4+ years of experience in Javascript, preferably Node.js and/or Typescript.</li> <li>4+ years of experience in RDBMS, such as PostgreSQL or MySQL.&nbsp;&nbsp;</li> <li>3+ years in roles involving operational responsibility for large-scale software systems (monitoring, alerting, production debugging, etc.). While we ultimately value expertise over experience, we expect that a successful candidate for this role will have 4+ years working with complex production systems.</li> <li>2+ years in formal or informal leadership roles that involve significant time mentoring and teaching co-workers about software best practices.</li> <li>Full stack engineering background, you are comfortable writing backend code and creating front-end UIs (we use Vue)</li> <li>Empathy and effective communication skills: you can advocate for teammates and stakeholders such as customers and product managers;&nbsp; you can explain complex technical issues to audiences of diverse technical understanding.</li> <li>Production experience with job-queueing systems, containers (Docker), and AWS services (SQS, S3, ECS)</li> </ul> <p>At Lob, we are looking to #LevelUp and #EmpowerDiversity, we invite you to apply if you possess even some of these:</p> <ul> <li>Ability to design and vet micro-service and cloud-based architectures at scale, as well as support your teammates in doing the same.</li> <li>Effective project management skills: track record of working together with product managers to bring projects from inception to completion.</li> </ul> <p><strong>Compensation information</strong></p> <p>CA/NYC Tier:</p> <p>Base: $170,000 - $178,500</p> <p>US Tier:</p> <p>Base: $160,000 - $168,500</p><div class="content-conclusion"><p><span style="font-weight: 300;">“Lob’s salary ranges are based on market data, relative to our size, industry and stage of growth. Salary is one part of total compensation, which also includes equity, perks and competitive benefits. Salary decisions are based on many factors including geographic location, qualifications for the role, skillset, proficiency and experience level. Lob reasonably expects to pay candidates who are offered roles within the provided salary ranges.”</span></p> <p><span style="font-weight: 300;">We offer remote working opportunities in AZ, CA, CO, DC, FL, GA, IA, IL, MA, MD, MI, MN, NE, NC, NH, NJ, NV, NY, OH, OR, PA, RI, TN, TX, UT, and WA,&nbsp;<span style="text-decoration: underline;"><strong>unless specified otherwise in the job description above.&nbsp;</strong></span></span></p> <p><span style="font-weight: 300;">If you are looking for a progressive, fun-spirited, and mentally stimulating environment, come join us at Lob!</span></p> <p>&nbsp;</p> <p><span style="color: #000000;"><strong>Our Commitment to Diversity</strong></span></p> <p><span style="color: #000000;"><span style="font-weight: 300;">Lob is an equal opportunity employer and </span><a style="color: #000000;" href="https://www.lob.com/blog/power-diversity-starts-data"><em><span style="font-weight: 300;">values diversity</span></em></a><span style="font-weight: 300;"> of </span><a style="color: #000000;" href="https://www.lob.com/blog/a-commitment-to-diversity"><em><span style="font-weight: 300;">backgrounds and perspectives</span></em></a><span style="font-weight: 300;"> to cultivate an environment of understanding to have greater impact on our business and customers. We encourage under-represented groups to apply and do not discriminate on the basis of race, religion, color, national origin, gender, sexual orientation, age, marital status, veteran status, disability status, or criminal history in accordance with local, state, and/or federal laws, including the </span><a style="color: #000000;" href="https://sfgov.org/olse/sites/default/files/Document/FCO%20Art.%2049%20Official%20Notice%20to%20print%202017.pdf"><em><span style="font-weight: 300;">San Francisco’s Fair Chance Ordinance</span></em></a><span style="font-weight: 300;">.</span></span></p> <p><span style="color: #000000;"><strong>Recent awards</strong></span></p> <p><span style="color: #000000;"><span style="font-weight: 300;"><img src="https://keep.google.com/u/0/media/v2/1e8T9oEtvbqRcrMcmtMSXLguNCPTDvK9fgYyRHPMut1prD3B1tXfjRFr3o2O1dlQ/1mas8D_M3MtQ6MJEDfG-6yRUXNoeICQQ-q7BzV0N3BOFVMtPtiGQm3VTYWAtzlnE?sz=512&amp;accept=image%2Fgif%2Cimage%2Fjpeg%2Cimage%2Fjpg%2Cimage%2Fpng%2Cimage%2Fwebp" alt="" width="NaN" height="NaN">BuiltIn Best Midsize Companies to Work For 2022</span><span style="font-weight: 300;"><br></span><span style="font-weight: 300;">#86 on Y Combinator's Top Private Companies List 2021</span><span style="font-weight: 300;"><br></span><span style="font-weight: 300;">BuiltIn Best Midsize Companies to Work For 2021</span><span style="font-weight: 300;"><br></span><span style="font-weight: 300;">2020 Inc 5000 List of the Fastest-Growing Private Companies</span><span style="font-weight: 300;"><br></span><span style="font-weight: 300;">2019 Timmy Awards - Best Tech Workplace for Diversity, Community Favorite in the Bay Area</span><span style="font-weight: 300;"><br></span><span style="font-weight: 300;">Deloitte’s 2019 Technology Fast 500<br><br></span></span></p></div>
Senior Engineering Manager, Data
United States
<div class="content-intro"><p><span style="font-weight: 300;">Lob was built by technical co-founders with a vision to make the world programmable.</span></p> <p><span style="font-weight: 300;">We offer two flagship APIs (print &amp; mail and address verification) that enable companies to send postal mail as effortlessly as sending emails. Lob is venture-backed by some of the most reputable investors in tech, and we are building our team to shape the future of our company and meet the demands of a quickly growing customer base and dynamic product offerings.&nbsp;</span></p> <p><span style="font-weight: 300;">As a proud Pledge 1% company, we’re committed to leveraging our product, partnerships, and people to drive positive social impact through </span><a href="http://www.lob.org"><em><span style="font-weight: 300;">Lob.org</span></em></a><span style="font-weight: 300;">, and are on a mission to make direct mail more sustainable.</span></p></div><p><strong>About The Team</strong></p> <p>At Lob, we love data: we believe that data is one of the most important advantages we have in an industry that’s ripe for innovation. From internal teams to external customers, we’ve seen the incredible power data has to offer and are ready to take this effort to the next level as we transform the direct mail and print industry by building data products.</p> <p>This role will lead a team of data engineers, scientists, and analysts, cultivating the existing foundation of data products across the whole of Lob. Our work interfaces with stakeholders from product, operations, finance, and the leadership team as well as external customers. In the first six months, you’ll develop and refine a data strategy for Lob and lead the team on execution of key data products.</p> <p><strong>As Senior Engineering Manager, Data you’ll...</strong></p> <ul> <li>Craft a vision and direction for data products at Lob–our leadership team believes that data is one of the key value props we bring to an industry ripe for technological disruption and you’ll help chart the course towards realizing that</li> <li>Partner with our cross-functional stakeholders to design clear interfaces, such as SLOs and SLAs, that both meet their needs of and align the team with our larger strategic vision</li> <li>Improve visibility into our data systems, giving our team and external teams, clear views into operational state and confidence in the accuracy and reliability of data</li> <li>Lead Lob’s push to use data to show ROI for our customer’s mail usage. This includes helping us solve for attribution and conversion across different channels (postal mail, email, sms, ads)</li> <li>Guide your team to execute on key initiatives such as mailpiece trackability, partner deliverability goals, and other workstreams aligned with company goals</li> <li>Deliver a reliable, scalable, and modern data system built on top of industry best practices (we use Airflow, DBT, and a data lake pattern, for example)&nbsp;</li> <li>Improve processes--project management, sprint management, stakeholder visibility--to help the team operate effectively</li> <li>Be a coach and enabler for your team, you’ll empower them, rather than tell them what to do. We see engineering management as a support role: you will help your team build problem-solving muscle by practicing active listening, asking good questions, and giving actionable, timely, kind, and direct feedback&nbsp;</li> <li>Engage, retain, and grow great problem-solvers and collaborators. You’ll be responsible for building diverse, inclusive teams, where everyone feels comfortable and safe being themselves at work; psychological safety is a first-order goal</li> </ul> <p><strong>What you will bring to this role...</strong></p> <ul> <li>At least 4 years of experience as a manager with a growth-oriented mindset. We’d love to hear how you’ve led teams through various stages of growth</li> <li>A track record of successful data product delivery in a variety of fast-moving environments. You’ve done engineering work at the senior level, solving complex technical challenges at scale. You’ve had to weigh difficult trade-offs and live with your decisions, and you can tell us what you’ve learned from them</li> <li>Some experience preferred working with a modern data stack, including Airflow, DBT, data lake patterns, etc</li> <li>Great communication skills. You should be able to explain your approach and the impact of your work to non-technical stakeholders in a way that is clear to them</li> <li>You seek to support your team, your stakeholders, and the company more broadly as a first-order consideration</li> <li>Since great technologists come from diverse backgrounds, it doesn’t particularly matter if you have a specific degree—we want to hear about your contributions in a business setting</li> <li>A love for the domain and an appreciation for educating others about the hidden power of data products</li> </ul> <p><strong>Compensation information</strong></p> <p><strong>CA/NYC Tier:</strong></p> <p>Base: $190,000 - $220,000</p> <p><strong>US Tier:</strong></p> <p>Base: $180,000 - $207,500</p> <p>&nbsp;</p> <p><span style="color: white;">&lt;#LI-REMOTE #LI-GD1</span></p><div class="content-conclusion"><p><span style="font-weight: 300;">“Lob’s salary ranges are based on market data, relative to our size, industry and stage of growth. Salary is one part of total compensation, which also includes equity, perks and competitive benefits. Salary decisions are based on many factors including geographic location, qualifications for the role, skillset, proficiency and experience level. Lob reasonably expects to pay candidates who are offered roles within the provided salary ranges.”</span></p> <p><span style="font-weight: 300;">We offer remote working opportunities in AZ, CA, CO, DC, FL, GA, IA, IL, MA, MD, MI, MN, NE, NC, NH, NJ, NV, NY, OH, OR, PA, RI, TN, TX, UT, and WA,&nbsp;<span style="text-decoration: underline;"><strong>unless specified otherwise in the job description above.&nbsp;</strong></span></span></p> <p><span style="font-weight: 300;">If you are looking for a progressive, fun-spirited, and mentally stimulating environment, come join us at Lob!</span></p> <p>&nbsp;</p> <p><span style="color: #000000;"><strong>Our Commitment to Diversity</strong></span></p> <p><span style="color: #000000;"><span style="font-weight: 300;">Lob is an equal opportunity employer and </span><a style="color: #000000;" href="https://www.lob.com/blog/power-diversity-starts-data"><em><span style="font-weight: 300;">values diversity</span></em></a><span style="font-weight: 300;"> of </span><a style="color: #000000;" href="https://www.lob.com/blog/a-commitment-to-diversity"><em><span style="font-weight: 300;">backgrounds and perspectives</span></em></a><span style="font-weight: 300;"> to cultivate an environment of understanding to have greater impact on our business and customers. We encourage under-represented groups to apply and do not discriminate on the basis of race, religion, color, national origin, gender, sexual orientation, age, marital status, veteran status, disability status, or criminal history in accordance with local, state, and/or federal laws, including the </span><a style="color: #000000;" href="https://sfgov.org/olse/sites/default/files/Document/FCO%20Art.%2049%20Official%20Notice%20to%20print%202017.pdf"><em><span style="font-weight: 300;">San Francisco’s Fair Chance Ordinance</span></em></a><span style="font-weight: 300;">.</span></span></p> <p><span style="color: #000000;"><strong>Recent awards</strong></span></p> <p><span style="color: #000000;"><span style="font-weight: 300;"><img src="https://keep.google.com/u/0/media/v2/1e8T9oEtvbqRcrMcmtMSXLguNCPTDvK9fgYyRHPMut1prD3B1tXfjRFr3o2O1dlQ/1mas8D_M3MtQ6MJEDfG-6yRUXNoeICQQ-q7BzV0N3BOFVMtPtiGQm3VTYWAtzlnE?sz=512&amp;accept=image%2Fgif%2Cimage%2Fjpeg%2Cimage%2Fjpg%2Cimage%2Fpng%2Cimage%2Fwebp" alt="" width="NaN" height="NaN">BuiltIn Best Midsize Companies to Work For 2022</span><span style="font-weight: 300;"><br></span><span style="font-weight: 300;">#86 on Y Combinator's Top Private Companies List 2021</span><span style="font-weight: 300;"><br></span><span style="font-weight: 300;">BuiltIn Best Midsize Companies to Work For 2021</span><span style="font-weight: 300;"><br></span><span style="font-weight: 300;">2020 Inc 5000 List of the Fastest-Growing Private Companies</span><span style="font-weight: 300;"><br></span><span style="font-weight: 300;">2019 Timmy Awards - Best Tech Workplace for Diversity, Community Favorite in the Bay Area</span><span style="font-weight: 300;"><br></span><span style="font-weight: 300;">Deloitte’s 2019 Technology Fast 500<br><br></span></span></p></div>
You may also like