Build Automated Email Sequences - Shootmail + Upstash Workflow (For Devs) | Shootmail

Personalized Email Marketing

Personalized email marketing is no longer a luxury, it’s a necessity. But for developers and SaaS owners, setting up reliable and engaging email sequences can feel like a constant battle. You’re juggling design, content, and the complexities of ensuring your emails actually get delivered. What if you could automate this entire process, creating powerful drip campaigns without sacrificing scalability or reliability?

That’s where Shootmail and Upstash Workflow come in. This guide will show you how to build robust email sequences and drip campaigns using Shootmail’s intuitive email builder and Upstash Workflow’s durable serverless functions. No more worrying about serverless function timeouts or lost leads – just scalable, personalized email marketing that works.

Understanding Email Sequences and Drip Campaigns

Before diving into the code, let’s clarify the basics:

Why are these strategies so important for SaaS businesses?

The Power of Shootmail for Email Creation

Stop wrestling with HTML and start crafting beautiful, high-converting emails with Shootmail.

Basic Example of the SDK

Here’s a basic example of initializing the Shootmail client and sending an email:

Install Shootmail’s SDK:

npm i shootmail

Initialize and Shoot:

import { Shootmail } from "shootmail";

//initialize Shootmail
const shootmail = new Shootmail({
  shootmailApiKey: "YOUR_SHOOTMAIL_API_KEY",
  providers: [
    {
      provider: "resend",
      apiKey: "YOUR_RESEND_API_KEY",
    },
  ],
});

//Shoot your mail
const response = await shootmail.shoot({
  templateId: "YOUR_TEMPLATE_ID",
  from: { email: "updates@mail.shootmail.app", name: "Shootmail" },
  to: [{ email: "user@example.com" }],
  subject: "Welcome to Our SaaS!",
  data: { userName: "John Doe" },
});

console.log(response);

Upstash Workflow: Reliable Automation for Email Sequences

Now that you’ve created your beautiful email templates with Shootmail, it’s time to automate the sending process with Upstash Workflow.

Building an Email Sequence with Shootmail and Upstash Workflow: A Code Example

Let’s build a welcome email sequence for new SaaS sign-ups. This sequence will consist of three emails:

  1. A welcome email sent immediately after sign-up.
  2. A follow-up email sent after three days.
  3. A final email sent after a week, encouraging users to upgrade.

Step 1: Setting up the Workflow Endpoint (Upstash Workflow)

First, we need to define a workflow endpoint using Upstash Workflow’s serve method. This endpoint will receive the initial user data and trigger the email sequence.

Install Upstash workflow SDK

npm install @upstash/workflow

Import and use:

import { serve } from "@upstash/workflow/nextjs";

export const { POST } = serve(async (context) => {
  const { userId, email } = context.requestPayload;

// Your email sequence logic will go here
});

Step 2: Sending the First Welcome Email (Shootmail SDK)

Now, let’s use the Shootmail SDK to send the initial welcome email. We’ll use the shoot method and provide the template ID, recipient email, and any personalized data.

import { serve } from "@upstash/workflow/nextjs";
import { Shootmail } from "shootmail";

export const { POST } = serve(async (context) => {
  const { userId, email } = context.requestPayload;

// Send the welcome email using Shootmail
  const shootmail = new Shootmail({
    shootmailApiKey: "YOUR_SHOOTMAIL_API_KEY",
    providers: [
      {
        provider: "resend",
        apiKey: "YOUR_RESEND_API_KEY",
      },
    ],
  });
  const response = await shootmail.shoot({
    templateId: "YOUR_WELCOME_TEMPLATE_ID",
    from: { email: "updates@mail.shootmail.app", name: "Shootmail" },
    to: [{ email: email }],
    subject: "Welcome to Our SaaS!",
    data: { userId: userId }, // any data for personalization
  });

console.log(response); // Log the response from Shootmail
});

Step 3: Delaying the Next Email (Upstash Workflow)

To delay the sending of the next email in the sequence, we’ll use Upstash Workflow’s context.sleep method. This will pause the workflow for three days.

import { serve } from "@upstash/workflow/nextjs";
import { Shootmail } from "shootmail";

export const { POST } = serve(async (context) => {
  const { userId, email } = context.requestPayload;

// Send the welcome email using Shootmail (as shown above)

// Delay the next email for three days
  await context.sleep("delay-follow-up", 3 * 24 * 60 * 60);
});

Step 4: Checking User Activity (Upstash Workflow)

Before sending the follow-up email, let’s check if the user has been active on our SaaS platform. We’ll need to integrate with your application’s data store to retrieve this information.

import { serve } from "@upstash/workflow/nextjs";
import { Shootmail } from "shootmail";

export const { POST } = serve(async (context) => {
  const { userId, email } = context.requestPayload;

// Send the welcome email using Shootmail (as shown above)

// Delay the next email for three days
  await context.sleep("delay-follow-up", 3 * 24 * 60 * 60);

// Check if the user has been active
  const isActive = await context.run("check-user-activity", async () => {
    const userActivity = await getUserActivity(userId);
    return userActivity.lastLogin > Date.now() - 3 * 24 * 60 * 60 * 1000; // Check if logged in within the last 3 days
  });
});

async function getUserActivity(userId: string) {
  // Implement your data store logic here
  return { lastLogin: Date.now() - 2 * 24 * 60 * 60 * 1000 }; // Example activity
}

Step 5: Sending a Follow-Up Email (Shootmail SDK)

Finally, let’s send a personalized follow-up email based on user activity.

import { serve } from "@upstash/workflow/nextjs";
import { Shootmail } from "shootmail";

export const { POST } = serve(async (context) => {
  const { userId, email } = context.requestPayload;

// Send the welcome email using Shootmail (as shown above)

// Delay the next email for three days
  await context.sleep("delay-follow-up", 3 * 24 * 60 * 60);

// Check if the user has been active
  const isActive = await context.run("check-user-activity", async () => {
    const userActivity = await getUserActivity(userId);
    return userActivity.lastLogin > Date.now() - 3 * 24 * 60 * 60 * 1000; // Check if logged in within the last 3 days
  });

// Send the follow-up email based on user activity
  if (isActive) {
    const response = await shootmail.shoot({
      templateId: "YOUR_ACTIVE_TEMPLATE_ID",
      from: { email: "updates@mail.shootmail.app", name: "Shootmail" },
      to: [{ email: email }],
      subject: "Welcome Back!",
      data: { userId: userId },
    });
    console.log(response);
  } else {
    const response = await shootmail.shoot({
      templateId: "YOUR_INACTIVE_TEMPLATE_ID",
      from: { email: "updates@mail.shootmail.app", name: "Shootmail" },
      to: [{ email: email }],
      subject: "We Miss You!",
      data: { userId: userId },
    });
    console.log(response);
  }
});

## Complete Example

Here is the complete email sequence example that is used in Shootmail to welcome and follow up the users:

### Coding email sequence

```tsx
import { serve } from "@upstash/workflow/nextjs";
import { Resend } from "@upstash/workflow/integrations/resend";

export const { POST } = serve(async (context) => {
  // Send email
  const payload = context.requestPayload;

if (!payload) {
    throw new Error("Payload not found");
    }

const result1 = await shootmail.shoot({
      templateId: "YOUR_WELCOME_TEMPLATE_ID",
      from: { email: "updates@mail.shootmail.app", name: "Shootmail" },
      to: [{ email: email }],
      subject: "Welcome to Our SaaS!",
      data: { userId: userId },
    });

console.log("Step 1 has been executed, result", result1);

await context.sleep("Step 2: Wait for 2 days", 2 * 24 * 60 * 60);

const result2 = await context.run("Step 3: Check if user has purchased a plan", async () => {
        const isPaidUser = await hasUserPurchasedPlan();

if (isPaidUser.isErr()) {
            return {
                isPaidUser: false,
                result: isPaidUser.error
            };
        }

console.log("isPaidUser", isPaidUser.value);

if (!isPaidUser.value) {
            const response = await shootmail.shoot({
                templateId: "YOUR_FOLLOW_UP_TEMPLATE_ID",
                from: { email: "updates@mail.shootmail.app", name: "Shootmail" },
                to: [{ email: email }],
                subject: "Special offer for you",
                data: { userId: userId },
            });

return {
                isPaidUser: false,
                result: response
            };
        } else {
            const response = await shootmail.shoot({
                templateId: "YOUR_FEEDBACK_TEMPLATE_ID",
                from: { email: "updates@mail.shootmail.app", name: "Shootmail" },
                to: [{ email: email }],
                subject: "Wanted to say Hi and get your feedback",
                data: { userId: userId },
            });

return {
                isPaidUser: true,
                result: response
            };
        }
    });

console.log("Step 3 has been executed, result", result2);
});

Triggering workflow

import { Client } from "@upstash/workflow";

const client = new Client({ token: c.env.QSTASH_TOKEN });

const { messageId } = await client.trigger({
     url: "your-workflow-endpoint",
     body: data,
     retries: 3
});

Advanced Email Sequence Strategies with Shootmail and Upstash Workflow

This is just the beginning! With Shootmail and Upstash Workflow, you can implement even more sophisticated email marketing strategies:

Shootmail and Upstash Workflow: The Perfect Combination for Developers

Building automated email sequences and drip campaigns doesn’t have to be a headache. Shootmail and Upstash Workflow empower developers to create powerful, personalized email marketing experiences with ease. With Shootmail’s intuitive email builder and SDK alongside Upstash Workflow’s reliable automation, you can focus on growing your SaaS business, not managing infrastructure.

Ready to level up your email marketing? Sign up for Shootmail and Upstash today and start building your own automated email sequences!