How to send personalized product emails: Connecting Shopify, Brevo, and Cloudhooks

Automating customer communications is key for any Shopify store. While Shopify provides basic email capabilities, integrating with a dedicated email service like Brevo unlocks powerful features for personalized transactional and marketing emails.

Brevo (formerly Sendinblue) is a leading email platform serving over 500,000 customers worldwide. When combined with Cloudhooks, you can create sophisticated email workflows triggered by any Shopify event—from order confirmations to product-specific welcome sequences.

In this article, we'll show you how to create an automated email workflow that sends personalized emails based on customer purchases. The example implementation is straightforward but powerful - feel free to improve or tweak it as you see fit.

What you’ll build

In this tutorial, you'll create an automation that:

  1. Monitors your Shopify store for new orders
  2. Extracts customer information and purchase details
  3. Selects a product-specific email template from Brevo
  4. Automatically sends a personalized welcome email to the customer

This integration enables you to:

  • Send different welcome emails based on specific products
  • Personalize content using customer data
  • Track email engagement through Brevo's analytics
  • Scale your email communications without manual intervention

Time to complete: 20 minutes
Difficulty level: intermediate

Prerequisites

  • A Shopify store with Cloudhooks installed
  • A Brevo account (free tier available)
  • Basic understanding of Shopify products and orders
  • Familiarity with email templates

Set up email templates in Brevo

First, we'll create email templates in Brevo that will be triggered based on specific product purchases. This allows you to send tailored welcome messages depending on what customers buy.

Create your templates

Follow these steps to set up your email templates:

1) Go to the “Campaigns / Templates” page in Brevo.

2) Press "Create Template" to create templates for every product.

3) Design your templates with product-specific content:

  • Welcome message tailored to the product
  • Product-specific onboarding instructions
  • Relevant cross-sell recommendations
  • Support contact information

Here is how our three templates look in Brevo:

Get template IDs

Each email template in Brevo has a unique identifier that we'll need for our integration:

  1. Open each template from your template list
  2. Look at the URL in your browser
  3. Note the numeric ID that appears after /template/ in the URL
  4. Save these IDs—you'll need them when configuring the hook

💡 Tip: Create a spreadsheet mapping product names to template IDs for easier reference.

Generate API credentials

To allow Cloudhooks to send emails through Brevo:

  1. Navigate to "SMTP & API" in the profile menu
  2. Select "API Keys"
  3. Click "Generate an API key"
  4. Configure the key settings:
    • Name: "Cloudhooks Integration"
  5. Click "Generate"
  6. Important: Copy and store your API key securely—it won't be shown again

⚠️ Security Note: Never share your API key or commit it to version control. If your key is compromised, generate a new one immediately and update your hook configuration.

Set up Shopify

Create test products

For this tutorial, we'll set up three products in Shopify to demonstrate different email scenarios. You can adapt this to your existing products later.

  1. Go to Products > Add product in your Shopify admin
  2. Create these example products:
    • Cloudhooks Mug (physical product welcome)
    • Cloudhooks Pro (software onboarding)
    • Cloudhooks Unlimited (premium customer welcome)

Get product IDs

Each product needs to be mapped to its corresponding email template:

  1. Open each product from your products list
  2. Find the product ID in the URL (it's the number after /products/)
  3. Create a mapping table:
Product name Product ID Template ID
Cloudhooks Mug 123456789 1
Cloudhooks Pro 987654321 2
Cloudhooks Unlimited 456789123 3

💡 Tip: This mapping will be used in your hook configuration to determine which email template to send.

Configure Cloudhooks

Now we'll create an automated workflow in Cloudhooks that sends personalized emails through Brevo whenever a customer places an order. This integration uses Shopify's order creation webhook and Brevo's email API.

Understanding the workflow

When a customer places an order, the hook will:

  1. Capture the order creation event from Shopify
  2. Extract customer details (name, email) and product information
  3. Look up the corresponding email template based on the purchased product
  4. Send a personalized email through Brevo's API
  5. Log the successful email delivery

Create the hook

Follow these steps to set up your automation:

1) Log into your Cloudhooks dashboard

2) Click "Create hook" in the top-right corner

Configure the trigger

1) In the "Trigger" tab:

  • Navigate to the "Order" category
  • Select "An order is created"
  • Click "Select trigger"

💡 Tip: The "An order is created" trigger fires immediately after checkout completion, ensuring timely email delivery.

Add the hook code

  1. Navigate to the "Hook" tab
  2. Copy the template code from the end of this article
  3. Update the configuration constants:
const BREVO_API_KEY = 'your-api-key-here';
const DEFAULT_NAME = 'Valued Customer';
const PRODUCT_TEMPLATE_MAP = {
  '123456789': '1',  // Mug product ID : template ID
  '987654321': '2',  // Pro product ID : template ID
  '456789123': '3'   // Unlimited product ID : template ID
};

⚠️ Important: Double-check your product and template IDs. Incorrect mappings will result in customers receiving the wrong emails.

Configure settings

Switch to the "Settings" tab, and configure the following:

  • Name: "Product-specific welcome emails via Brevo"
  • Status: Toggle to "Active"

💡 Best Practice: Use a clear naming convention that indicates both the trigger (new order) and action (Brevo email) for easier management.

Save and activate

  1. Click "Save" in the top-right corner
  2. Verify the hook appears as "Active" in your dashboard

⚠️ Note: After saving, the hook will immediately begin processing new orders. Ensure your email templates and product mappings are correct before activating.

Testing your integration

Before activating the hook for real customers, it's essential to thoroughly test the integration. We'll cover two testing approaches: using the test payload and performing a live test purchase.

Method 1: Test payload simulation

This method allows you to test the integration without making actual purchases:

1) Navigate to the "Hook" tab in your hook configuration

2) In the "Payload" pane on the right, locate these key properties:

{
  "customer": {
    "email": "your-test@email.com",
    "first_name": "Test",
    "last_name": "Customer"
  },
  "line_items": [
    {
      "product_id": "123456789"
    }
  ]
}

3) Modify the test payload:

  • Set a valid email address you can access
  • Update the customer name fields
  • Enter one of your mapped product IDs

4) Click "Run test"

5) Monitor the execution:

  • Check the "Test" pane for successful API calls
  • Verify the email arrives in your inbox
  • Confirm the correct template was used

💡 Tip: Test each product-template mapping to ensure all variations work correctly.

Method 2: Live test purchase

For end-to-end testing using Shopify's test payment gateway:

1) Enable test mode in your Shopify payments settings

2) Place a test order:

  • Add a product to cart
  • Complete checkout using test card details
  • Use an email address you can access

3) Monitor the results:

  • Check Cloudhooks logs for successful execution
  • Verify email delivery and content
  • Confirm personalization elements

⚠️ Important: Complete this validation checklist before going live:

  • Test all product-template combinations
  • Verify personalization variables work correctly
  • Check email formatting on multiple devices
  • Confirm proper error handling
  • Test with missing customer information
  • Verify email delivery speed

Understanding your hook

How the hook works

The hook processes each order through several steps:

  1. Event capture
    • Receives the Shopify order webhook
    • Validates the payload structure
  2. Data extraction
    • Retrieves customer information (name, email)
    • Identifies purchased products
    • Handles missing or incomplete data
  3. Template selection
    • Looks up the correct template using product mapping
    • Falls back to default template if needed
  4. Email personalization
    • Prepares customer data for the template
    • Formats names and other variables
  5. Email delivery
    • Calls Brevo's API with prepared data
    • Handles success/failure responses
    • Logs the operation result

Troubleshooting common issues

No email received

  • Check Cloudhooks logs for API errors
  • Verify email address formatting
  • Confirm template ID mapping

Wrong template sent

  • Double-check product ID mapping
  • Verify template IDs in Brevo
  • Review hook configuration

API errors

  • Validate API key permissions
  • Check for rate limiting
  • Verify payload formatting

Security considerations

  1. Never commit API keys to version control
  2. Validate all incoming data
  3. Handle API errors gracefully
  4. Log sensitive information securely
  5. Use HTTPS for all API calls

⚠️ Important: Replace placeholder values before activating the hook.

Hook code


const BREVO_API_KEY = 'YOUR_BREVO_API_KEY';
const DEFAULT_FIRST_NAME = 'Customer';
const PRODUCTS_EMAIL_TEMPLATES = [
    {
      productId:        7110439927891,
      emailTemplateId:  1
    },
    {
      productId:        6705843699795,
      emailTemplateId:  2
    },
    {
      productId:        6705843896403,
      emailTemplateId:  3
    },
  ];

module.exports = async function(payload, actions) {
    const httpConfig = {
    headers: {
      'accept': 'application/json',
      'content-type': 'application/json',
      'api-key': `${BREVO_API_KEY}`
    }
  };


  function findEmailTemplate(productId) {
      let product = PRODUCTS_EMAIL_TEMPLATES.find((product) => product.productId === productId);
      return product ? product.emailTemplateId : null;
  }  


  function extractProductIdFromPayload(payload) {
    if (payload.line_items && payload.line_items.length > 0) {
      return payload.line_items[0].product_id;
    } else {
      throw new Error('No product was purchased!');
    }
  }

  function extractNameFromPayload(payload) {
    let result = '';

    if (payload.customer.first_name) result += payload.customer.first_name + ' ';
    result += payload.customer.last_name;

    return result;
  }

  function extractFirstNameFromPayload(payload) {
    return payload.customer.first_name ?? DEFAULT_FIRST_NAME;
  }

  function extractEmailFromPayload(payload) {
    return payload.customer.email;
  }

  const productId = extractProductIdFromPayload(payload);
  const emailTemplateId = findEmailTemplate(productId);

  if (emailTemplateId) {
    try {
      const email = extractEmailFromPayload(payload);
      const firstName = extractFirstNameFromPayload(payload);
      const fullName = extractNameFromPayload(payload);

      const sendEmailParams = {
        'to': [
          {
            'email': email,
            'name':  fullName, 
          }
        ],
        'templateId': emailTemplateId,
        'params': {
          'email': email,
          'name': fullName,
          'firstName': firstName
        }
    };

      const {data: result} = await actions.http.post(
        'https://api.brevo.com/v3/smtp/email',
        sendEmailParams,
        httpConfig
      );

      console.log('Send email result: ', result);
    } catch (err) {
      console.log('Send email error: ' + err);
    }    
  } else {
    console.log(`No email sent for product: ${productId}`);
  }
};