Automatic Mail Campaign Creation with Mailjet
Tags: newsletter, mailjet, campaign, nestjs
Published: 2021-09-02 14:37:57

Hi Sparta!

In this article I will share with you **how to create marketing campaigns, newsletters... automatically** in your NestJS backend 💌

**The full source code and the documentation is available [on GitHub](https://github.com/arthurPrvst/automatic-campaign-mailjet) or [on FMP](https://fast-modular-project.com/modules/automatic-campaign-creation-mailjet)** 🙂

This newsletter / marketing campaign module will be added top of the React/Node/MySQL starter. This starter has already been presented to you in [this article](https://dev.to/fastmodularproject/web-starter-react-nestjs-mysql-3o9i).

# How does it work ?
We'll use Mailjet's API in order to:
- Create a "Contact" for every user of your app
- Add them to an already existing ContactList created on Mailjet side
- Update their metadatas (whether or not their profil are verified)
- Create campaign draft
- Send a test mail to a dev adress in order to preview the futur campaign that will be sent
- Schedule the campaign for all user's missing the verification of their profil

# High picture of the workflow
- A user sign up to your web app.
- A user is created in databse and on Mailjet side as a "Contact" (name, email, hasVerifiedProfil)
- Every day a 6pm05 we generate automatically a campaign draft to ask for the verification of their account (for user's who haven't done it before).
- The campaign is scheduled for 6pm35.
- The draft is sent to you, in order to verify their is no issue in content that will be sent to your user. If an issue occurs, you can delete the scheduled campaign in your Mailjet account. You could then retrigger the campaign generation with Postman once the content is corrected.


# Step by step guide

* 1 - Account creation

Create a MailJet account [here](https://fr.mailjet.com). </br>

* Step 2 - Install mailjet dependency

Install the `node-mailjet` dependency in the `backend` directory of your project.

```
npm install node-mailjet@3.3.1
```

* Step 3 - Mailjet credentials

Add your mailjet API credentials in your environments files (DEV, STAGING & PROD) found in the `backend/src/environments` directory.

```
export const environment = {
  ...,
  mailjet: {
    apiKey: '%YOUR_API_KEY%',
    secretKey: '%YOUR_SECRET_KEY%',
    contactListID: TODO_LATER,
  },
  ...
};
```

Your credentials can be found using [this link](https://app.mailjet.com/account/api_keys).

* Step 4 - Contact lists config
Create two contact lists in your Mailjet account. One will be used in dev env `mylist_dev` and the other one will be used for production `mylist_prod`.

To do so, in your Mailjet account : "Contact" > "Contact List" > "Create a contact a list".

Properties of your user should contains at least "email" (string), "name" (string) and hasVerified (boolean).

Once created, the the contactListID in `backend/src/environments` in the mailjet config.

* Step 5 - Segment config
A segment is a subset of contacts from a contact list that matchs your condition on the metadatas of the contact.
In our case, we'll create a segment "verification_not_done" that will contains all contact from `mylist_prod` having `hasVerified` properties equal to `false`.

* Step 6 - Mail template config
Create your campaign template with your Mailjet account : "Models" > "My Marketing Models" > "Create a new model". </br>
Once created, copy the ID of the template and set it as value of `ACCOUNT_VERIFICATION_TEMPLATE` in `campaign-templates.enum.ts`.

### Step 7 - Back
Add folder `backend/campaign` in your `backend/src/api`. </br>
Don't forget to add `CampaignModule` in the imports of the `app.module`.

Add folder `backend/mailer` in your `backend/src/shared`. 
Don't forget to add `MailerModule` in the imports of the `app.module`.

### Step 8 - Contact creation on sign up
When your user sign up, you should create a contact on mailjet side.

To do so, in file `backend/src/api/auth.controller.ts` add:

```
import { MailerService } from '../../shared/mailer/mailer.service';

...

    @Post('signup')
    async signUp(@Body() createUserDto: CreateUserDto): Promise<{ success: boolean, token?: string, id?: number }> {
        
        ...

        const mailjetContact = await this.mailService.createContact(user);

        if (mailjetContact.body.Data[0].ID) {
            console.log("Mailjet contactID", mailjetContact.body.Data[0].ID);
            await this.mailService.addContactToContactList(mailjetContact.body.Data[0].ID);

            await this.usersService.update(user, { contactId: mailjetContact.body.Data[0].ID });
            await this.mailService.updateDefaultContactMetadatas(mailjetContact.body.Data[0].ID, createUserDto.firstname);
        }
```

You can then verify in your contactList on your mailjet acccount the new user created on sign up.

### Step 9 - Automatic campaign creation
Every friday at 6pm05, your campaign will be created, and scheduled at 6pm35 on all users that did not verify their account.
```
    // Every friday at 6pm05
    @Cron('0 5 18 * * 5', {
        name: 'sendMarketingCampaignVerifyAccount',
        timeZone: 'Europe/Paris',
    })
    async sendMarketingCampaignVerifyAccount() {
        ...
    }
```

To make the [NestJS cron](https://docs.nestjs.com/techniques/task-scheduling) work, please install following dependencies: 
```
    npm install --save @nestjs/schedule
    npm install --save-dev @types/cron
```


### Bonus

To avoid any issue being categorized as "SPAM" you should configure the SPF and DKIM configuration for your sending mail address and your domain : Mailjet profil > "Preferences" > "Domains" > "DKIM/SPF authentication".


# Conclusion
I hope this module will help you ! Do not hesitate to **pin and star on GitHub** if you appreciated the article ❤️

Links:
* The platform sharing the starter and it's modules: [Fast Modular Project](https://fast-modular-project.com)
* Module "Automatic campaign Mailjet" on [GitHub](https://github.com/arthurPrvst/automatic-campaign-mailjet).