By Nancy Luu
Intro
Lob is a platform that automates the sending of direct mail, making it as easy as sending an email. With the Lob API, you can send an audience file that includes 3rd and 1st party data along with a creative file that has HTML conversion and dynamic parameters. Lob’s HTML templates support the inclusion of dynamic fields, called merge variables, which can be populated individually for each mail piece. Once Lob validates the send address, they forward your file to their print partners who send the prints through USPS. At the end of the process, you’ll receive analytics. This article outlines building dynamically personalized creatives through the use of merged variables as a linchpin of Lob’s utility, allowing for a sophisticated and tailored approach to content generation.
Diagram illustrating Lob’s real-time direct mail engagement.
Diagram by Lob.js
Context
Through Program Equity’s application Amplify, community members can champion campaigns for sustainability, fostering activism, and catalyzing substantive change. We aim to streamline community advocacy by leveraging the Lob API to craft tailored letters for local representatives to receive. The following examples serve as a foundational representation of our application, offering a generalized overview and providing a starting point for potential implementations.
Implementation
Frontend
In the Amplify application, we defined a Vue component (LetterLoad.vue
) to represent the frontend template for composing and displaying letters. Merge variables in HTML templates are placeholders that allow dynamic content insertion during runtime. In Vue components, you can use double curly braces ({{ }}
) to define and utilize merge variables. For instance, if you have an input field in a Vue component, you can capture user input and then use the merge variable syntax to dynamically insert this input into your HTML template.
<template>
<div>
<label for="userInput">Enter Your Name:</label>
<input v-model="userName" id="userInput" />
<label for="constituentInput">I'm in support because:</label>
<textarea v-model="constituentInput" id="constituentInput"></textarea>
<!-- Using merge variable to display user input dynamically -->
<p>My name is {{ userName }}.</p>
<p>{{ constituentInput }}</p>
</div>
</template>
<script>
export default {
data() {
return {
userName: '', // Initialized to an empty string
constituentInput: ''
};
}
};
</script>
Backend
While Amplify had various Express routes, such as those for fetching specific letter templates and validating addresses via the Lob API, let’s narrow our focus to a post route named /generateLetter
and dive into the details of merge variables to stay on track. Here is the whole request but let’s break this down step by step:
const express = require('express');
const Lob = require('lob');
const router = express.Router();
const lobApiKey = process.env.LOB_API_KEY; // Assuming you have a Lob API key stored in an environment variable
const lob = new Lob({ apiKey: lobApiKey });
router.post('/generateLetter', async (req, res) => {
try {
const { userName, constituentInput } = req.body;
// Check against Lob's constraints
const mergeVariablesString = JSON.stringify({ userName, constituentInput });
if (mergeVariablesString.length > 25000) {
return res
.status(400)
.json({
msg: "Merge variables payload exceeds Lob's character limit."
})
.end();
}
// Creating the HTML content of the letter with merge variables
const letterBody = `
<p>My name is {{userName}}.</p>
<p>{{constituentInput}}</p>
`;
// Creating Lob letter
const letter = await lob.letters.create({
description: 'Generated Letter',
to: {
name: 'Recipient Name',
address_line1: 'Recipient Address Line 1',
address_line2: 'Recipient Address Line 2',
address_city: 'Recipient City',
address_state: 'Recipient State',
address_zip: 'Recipient Zip Code',
},
from: 'Your Name',
file: letterBody,
color: false,
merge_variables: {
userName,
constituentInput,
},
});
// Assuming you want to send back Lob's response or any other relevant data
res.status(200).json({ letterId: letter.id, expectedDeliveryDate: letter.expected_delivery_date });
} catch (error) {
console.error('Error:', error);
res.status(500).json({ error: 'Internal Server Error' });
}
});
module.exports = router;
Before anything is done within the route we need to ensure that the merge variables payload is within Lob’s constraints. Any type of value is accepted as long as the object is valid JSON. You can use strings, numbers, booleans, arrays, objects, or null. The max length of the object is 25,000 characters.
(Note: Your variable names cannot contain any whitespace or any of the following special characters:
!, ", #, %, &, ', (, ), *, +, ,, /, ;, <, =, >, @, [, \, ], ^, `, {, |, }, ~.)
const mergeVariablesString = JSON.stringify({ userName, constituentInput });
if (mergeVariablesString.length > 25000) {
return res
.status(400)
.json({
msg: "Merge variables payload exceeds Lob's character limit."
})
.end();
}
This post request expects a request body to contain the userName and constituentInput fields we defined in the component above. The route then creates HTML content for the letter using these variables and submits the data in the ‘file’ field to Lob API to generate the letter. Remember, it is important to utilize the merge variable syntax within the letter body to ensure dynamic content is correctly passed to Lob API.
const letterBody = `
<p>My name is {{userName}}.</p>
<p>{{constituentInput}}</p>
`;
This next section uses the Lob SDK to create a new letter. The lob.letters.create method is called with an object containing various parameters. (Note: to and from could also have been merge variables.)
const letter = await lob.letters.create({
description: 'Generated Letter',
to: {
name: 'Recipient Name',
address_line1: 'Recipient Address Line 1',
address_line2: 'Recipient Address Line 2',
address_city: 'Recipient City',
address_state: 'Recipient State',
address_zip: 'Recipient Zip Code',
},
from: 'Your Name',
file: letterBody,
color: false,
merge_variables: {
userName,
constituentInput,
},
});
And finally, assuming the Lob Letter creation is successful, the server responds with a JSON object containing information about the generated letter such as its letterId and the expectedDeliveryDate. If an error occurs, it is caught and logged to the console and an HTTP status of 500 is sent to the client.
// Assuming you want to send back Lob's response or any other relevant data
res.status(200).json({ letterId: letter.id, expectedDeliveryDate: letter.expected_delivery_date });
} catch (error) {
console.error('Error:', error);
res.status(500).json({ error: 'Internal Server Error' });
}
Conclusion
Utilizing the power of Lob’s API for dynamically personalized direct mail campaigns opens up a world of possibilities for community advocacy and engagement. I hope this article can serve as a building block for your understanding of Lob and its capabilities. I encourage you to explore innovative ways to leverage technology and effect positive change in your communities. It truly shines when used for good!
References:
Top comments (0)