npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@kb0912/notification-brevo

v2.1.1

Published

Sending email notification using Brevo.

Readme

@kb0912/notification-brevo

Brevo (formerly Sendinblue) notification plugin for Medusa v2. Handles transactional emails, automated marketing campaigns, contact sync, and event tracking — all configurable from the Medusa Admin.

Features

📧 Transactional Emails

Automatically sends Brevo transactional emails on Medusa events:

| Event | Trigger | Template Params | |---|---|---| | Order Placed | order.placed subscriber | order_id, display_id, total, items[], shipping_address, payment_collections[] | | Order Canceled | order.canceled subscriber | order_id, display_id, customer_name | | Order Delivered | order.completed subscriber | customer_name, order.display_id, order.items[], order.total | | Customer Created | customer.created subscriber | name, phone, customer_id | | Shipment Confirmed | shipment.created subscriber | customer_name, tracking_number, tracking_url, order.items[] |

Each event can be individually enabled/disabled and assigned its own Brevo template ID from the Admin UI.


🎁 Promotion — New Customer Welcome

When a new customer registers, the plugin can auto-create a unique discount code and send it via email.

How it works:

  1. Customer registers → customer.created event fires
  2. Plugin creates a Medusa Promotion with:
    • Code: {PREFIX}-{8-char random} (e.g. WELCOME-A3KF8X2N)
    • Rules: customer_id eq {customer} (locked to this customer only)
    • Rules: currency_code ne {excluded} (optional currency exclusions)
    • Campaign: time-bounded with starts_at / ends_at
    • Budget: usage limit = 1 (single use)
  3. Sends promotion email with the code

Admin Settings:

  • Enable/disable auto-create
  • Discount type: percentage or fixed
  • Discount value (e.g. 10%)
  • Expiry days (default: 30)
  • Code prefix (default: WELCOME)
  • Excluded currencies (e.g. VND)

⏰ Discount Expiry Reminder

A daily scheduled job checks for promotions about to expire and sends reminder emails.

How it works:

  1. Job runs daily at 9:00 AM (0 9 * * *)
  2. Queries all active promotions matching the configured code prefix
  3. Checks campaign ends_at within the reminder window (e.g. 3 days before expiry)
  4. Finds the associated customer via customer_id rule on the promotion
  5. Sends reminder email (once per promotion, tracked in customer metadata)

Admin Settings:

  • Enable/disable reminder
  • Days before expiry to send (default: 3)
  • Reminder template ID

🛒 Abandoned Cart Recovery

Multi-step abandoned cart email sequence with optional discount code on the final email.

How it works:

  1. Scheduled job runs every 15 minutes (*/15 * * * *)
  2. Finds carts where:
    • completed_at is null (not checked out)
    • Has an email address
    • Has at least 1 item
    • Last item activity exceeds the configured interval
  3. Sends emails based on configurable intervals (e.g. 1h, 24h, 72h)
  4. Tracks sent emails in cart metadata (abandonedcart_mail_1, abandonedcart_mail_2, ...)
  5. Only one email is sent per cart per job run

Discount on final email:

On the last interval, the plugin can auto-create a limited-time discount:

  • Code: {PREFIX}-{8-char random} (e.g. COMEBACK-V7KFPPC4)
  • Rules: customer_id eq {customer} (if cart has a logged-in customer)
  • Rules: currency_code ne {excluded} (optional currency exclusions)
  • Campaign: time-bounded (default: 48 hours)
  • Budget: usage limit (default: 1)

Duplicate prevention:

  • Discount creation and email sending use separate metadata flags
  • If discount is created but email fails → next run retries email using the existing discount code (no duplicate)
  • If user returns and updates cart → timer resets based on latest item activity, but already-sent email flags persist

Admin Settings:

  • Enable/disable abandoned cart
  • Intervals (JSON array of hours, e.g. [1, 24, 72])
  • Max emails per cart
  • Enable/disable discount on final email
  • Discount type, value, max uses, expiry hours
  • Code prefix (default: COMEBACK)
  • Excluded currencies
  • Separate template ID for discount email

⭐ Review Request

Sends review request emails for completed orders after a configurable delay.

  • Job schedule: daily at 10:00 AM
  • Only sends for orders with status "completed" (no returns/refunds)
  • Tracks sent status in order metadata to prevent duplicates

Admin Settings:

  • Enable/disable
  • Days after delivery (default: 7)
  • Template ID

💌 Win-back Campaign

Re-engages inactive customers who haven't ordered in a while.

  • Job schedule: daily at 11:00 AM
  • Finds customers whose last completed order was X+ days ago
  • Sends a win-back email (once per customer, tracked in metadata)

Admin Settings:

  • Enable/disable
  • Days inactive threshold (default: 30)
  • Template ID

👥 Brevo Contact Sync

Automatically syncs new customers to a Brevo contact list.

  • Creates/updates Brevo contacts with FIRSTNAME, LASTNAME, PHONE
  • Optionally adds contacts to a specific list ID

Admin Settings:

  • Enable/disable
  • Brevo List ID

📊 Event Tracking

Sends custom events to Brevo for analytics and automation triggers.

Tracked events:

  • customer_created — when a new customer registers
  • order_placed — when an order is placed

Admin Settings:

  • Enable/disable

🌐 Multi-language Templates

Override template IDs per locale for multilingual stores.

How it works:

  • Customer's preferred locale is read from customer.metadata.preferred_locale
  • If a locale-specific template exists for the event → use it
  • Otherwise → fallback to the default template

Admin Settings:

  • Enable/disable
  • JSON template map: { "vi": { "order.placed": 101, "order.canceled": 102 }, "en": { ... } }

Installation

# Install the plugin
yarn add @kb0912/notification-brevo

# Or link locally for development
yalc add @kb0912/notification-brevo

Configuration

1. Register the plugin in medusa-config.ts

import { defineConfig } from "@medusajs/framework/utils"

export default defineConfig({
  // ...
  plugins: [
    {
      resolve: "@kb0912/notification-brevo",
      options: {},
    },
  ],
  modules: [
    {
      resolve: "@medusajs/medusa/notification",
      options: {
        providers: [
          {
            resolve: "@kb0912/notification-brevo/providers/notifications-brevo",
            id: "brevo",
            options: {
              channels: ["email"],
              apiKey: process.env.BREVO_API_KEY,
              from: process.env.BREVO_FROM_EMAIL,
              senderName: process.env.BREVO_SENDER_NAME,
              // Optional: env-level template ID fallbacks
              orderPlacedTemplateId: process.env.BREVO_ORDER_PLACED_TEMPLATE_ID,
              orderCanceledTemplateId: process.env.BREVO_ORDER_CANCELED_TEMPLATE_ID,
              customerCreatedTemplateId: process.env.BREVO_CUSTOMER_CREATED_TEMPLATE_ID,
              shipmentConfirmedTemplateId: process.env.BREVO_SHIPMENT_CONFIRMED_TEMPLATE_ID,
              abandonedCartTemplateId: process.env.BREVO_ABANDONED_CART_TEMPLATE_ID,
            },
          },
        ],
      },
    },
  ],
})

2. Environment Variables

BREVO_API_KEY=xkeysib-xxxxxxxx
[email protected]
BREVO_SENDER_NAME="Your Store"

3. Run Migrations

npx medusa db:migrate

4. Admin Settings

Navigate to Settings → Brevo in the Medusa Admin to configure:

  • Template IDs for each event
  • Enable/disable individual features
  • Promotion settings (discount type, value, prefix, currency exclusions)
  • Abandoned cart intervals and discount settings
  • Contact sync, event tracking, and multi-language options

Brevo Template Variables

Use these variables in your Brevo email templates:

Order Placed

{{ params.order_id }}
{{ params.display_id }}
{{ params.customer_name }}
{{ params.total }}
{{ params.date_placed }}
{{ params.shipping_address.first_name }}
{{ params.shipping_address.address_1 }}
{{ params.shipping_address.city }}
{% for item in params.items %}
  {{ item.title }} × {{ item.quantity }} — {{ item.total }}
{% endfor %}

Customer Created

{{ params.name }}
{{ params.customer_id }}

Promotion (Welcome / Expiry Reminder)

{{ params.first_name }}
{{ params.promotion_code }}
{{ params.ends_at }}
{{ params.days_left }}        <!-- expiry reminder only -->

Abandoned Cart

{{ params.name }}
{% for item in params.items %}
  {{ item.title }} × {{ item.quantity }} — {{ item.unit_price }}
{% endfor %}
{{ params.promotion_code }}           <!-- if discount enabled -->
{{ params.discount_value }}           <!-- e.g. 10 -->
{{ params.discount_type }}            <!-- "percentage" or "fixed" -->
{{ params.discount_expires_at }}      <!-- ISO date string -->

Shipment Confirmed

{{ params.customer_name }}
{{ params.tracking_number }}
{{ params.tracking_url }}
{{ params.order.display_id }}
{% for item in params.order.items %}
  {{ item.title }} × {{ item.quantity }}
{% endfor %}

Review Request

{{ params.customer_name }}
{{ params.display_id }}
{% for item in params.items %}
  {{ item.title }}
{% endfor %}

Win-back

{{ params.customer_name }}
{{ params.last_order_date }}
{{ params.days_inactive }}

Development

# Watch for changes (plugin development)
yarn dev

# Build for production
yarn build

License

MIT