Overview
Icon for Ecomail

Ecomail

Automate Ecomail email marketing

medusa-plugin-ecomail

Ecomail integration plugin for Medusa v2 - email marketing and transaction tracking.

Features

  • πŸ“§ Subscriber Management - Add, update, and manage Ecomail subscribers
  • πŸ›’ E-commerce Tracking - Automatically track order transactions in Ecomail
  • 🎯 Smart Subscription - Intelligent handling of new subscribers, updates, and resubscriptions
  • 🎨 Admin UI - Built-in admin panel for testing and managing subscribers
  • πŸ”„ Auto-sync - Automatic synchronization of customer data with Ecomail lists

Compatibility

This plugin is compatible with Medusa v2 (>= 2.11.2).

Installation

npm install medusa-plugin-ecomail
# or
yarn add medusa-plugin-ecomail

Configuration

Basic Configuration (Default Mode)

Add the plugin to your Copy to clipboardmedusa-config.ts:

import { defineConfig } from '@medusajs/framework/utils'
export default defineConfig({
plugins: [
{
resolve: 'medusa-plugin-ecomail',
options: {
ecomailListId: process.env.ECOMAIL_LIST_ID,
ecomailToken: process.env.ECOMAIL_TOKEN,
shopDomain: process.env.SHOP_DOMAIN, // optional
},
},
],
})

Default Behavior: All customers are automatically synced to Ecomail when they place an order.

GDPR-Compliant Configuration

For GDPR compliance, enable explicit consent requirement:

import { defineConfig } from '@medusajs/framework/utils'
export default defineConfig({
plugins: [
{
resolve: 'medusa-plugin-ecomail',
options: {
ecomailListId: process.env.ECOMAIL_LIST_ID,
ecomailToken: process.env.ECOMAIL_TOKEN,
shopDomain: process.env.SHOP_DOMAIN, // optional
requireExplicitConsent: true, // Only sync with explicit consent
consentMetadataKey: 'ecomail_consent', // optional, this is the default
},
},
],
})

GDPR Behavior: Only customers who explicitly consent are synced to Ecomail.

Environment Variables

Add these to your Copy to clipboard.env file:

ECOMAIL_LIST_ID=your_list_id
ECOMAIL_TOKEN=your_api_token
SHOP_DOMAIN=your-shop.com # optional

Configuration Options

Option Type Required Default Description Copy to clipboardecomailListId string Yes - Your Ecomail list ID Copy to clipboardecomailToken string Yes - Your Ecomail API token Copy to clipboardshopDomain string No Copy to clipboard'' Your shop domain for transaction tracking Copy to clipboardrequireExplicitConsent boolean No Copy to clipboardfalse Require explicit consent before syncing customers Copy to clipboardconsentMetadataKey string No Copy to clipboard'ecomail_consent' Metadata key to check for consent

Automatic Syncing

The plugin automatically syncs customers to Ecomail when orders are placed. No additional code is required!

How It Works

  1. Customer places an order β†’ Copy to clipboardorder.placed event fires
  2. Plugin checks consent (if Copy to clipboardrequireExplicitConsent is enabled)
  3. Syncs customer data to Ecomail list
  4. Tracks transaction for e-commerce analytics

Default Mode (Copy to clipboardrequireExplicitConsent: false)

All customers are automatically synced to Ecomail when they place an order. No consent checking is performed.

GDPR Mode (Copy to clipboardrequireExplicitConsent: true)

Only customers who explicitly consent are synced. The plugin checks for consent in order or customer metadata.

How to pass consent from your storefront:

When completing checkout, include the consent flag in the order metadata:

// Example: Next.js/React storefront
const completeCheckout = async () => {
await sdk.store.cart.complete(cartId, {
metadata: {
ecomail_consent: userAcceptedNewsletter, // true or false
},
})
}
// Example: In a custom checkout flow
await fetch('/store/checkout/complete', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
cart_id: cartId,
metadata: {
ecomail_consent: true, // User checked the newsletter box
},
}),
})

The plugin checks for consent in this order:

  1. Order metadata (Copy to clipboardorder.metadata.ecomail_consent)
  2. Customer metadata (Copy to clipboardcustomer.metadata.ecomail_consent)

If consent is Copy to clipboardtrue, the customer is synced. If Copy to clipboardfalse or missing (in GDPR mode), the sync is skipped.

You can use a different metadata key for consent:

{
resolve: 'medusa-plugin-ecomail',
options: {
// ... other options
requireExplicitConsent: true,
consentMetadataKey: 'marketing_consent', // Use your own key
}
}

Then pass it from your storefront:

metadata: {
marketing_consent: true
}

Usage

In Your Code

Import and use the Ecomail service in your custom modules, subscribers, or workflows:

import { ECOMAIL_MODULE } from 'medusa-plugin-ecomail'
import type EcomailService from 'medusa-plugin-ecomail'
// In a subscriber or workflow
const ecomailService = container.resolve<EcomailService>(ECOMAIL_MODULE)
// Add a subscriber
await ecomailService.addSubscriber({
email: 'customer@example.com',
name: 'John',
surname: 'Doe',
city: 'Prague',
country: 'CZ',
})
// Smart add/update (checks if exists, handles resubscriptions)
await ecomailService.addSubscriberToListIfNotAdded({
email: 'customer@example.com',
name: 'John',
surname: 'Doe',

Admin Panel

The plugin adds an Ecomail settings page to your Medusa admin panel where you can:

  • Test subscriber operations (Check, Add, Update, Smart Add)
  • View subscriber details
  • Verify plugin configuration

Access it at: Settings β†’ Ecomail

API Reference

EcomailService Methods

Copy to clipboardaddSubscriber(data: SubscriberDataT)

Adds a new subscriber to the Ecomail list.

Parameters:

  • Copy to clipboarddata.email (required) - Subscriber email
  • Copy to clipboarddata.name - First name
  • Copy to clipboarddata.surname - Last name
  • Copy to clipboarddata.city - City
  • Copy to clipboarddata.country - Country code
  • Copy to clipboarddata.zip - Postal code
  • Copy to clipboarddata.company - Company name
  • Copy to clipboarddata.street - Street address
  • Copy to clipboarddata.phone - Phone number

Copy to clipboardgetExistingSubscriber(email: string)

Retrieves an existing subscriber from the list.

Copy to clipboardupdateSubscriber(data: SubscriberDataT)

Updates an existing subscriber's data.

Copy to clipboardaddSubscriberToListIfNotAdded(data: SubscriberDataT)

Smart method that:

  • Adds subscriber if they don't exist
  • Updates subscriber if they exist and are subscribed
  • Resubscribes if they exist but are unsubscribed

Copy to clipboardaddTransaction(order: OrderDTO, customer: CustomerDTO)

Tracks an e-commerce transaction in Ecomail with order details and items.

Custom Integration Examples

Using the Service Directly

While the plugin automatically syncs on order placement, you can also use the service directly for custom scenarios:

// Example: Add subscriber on customer registration
import { SubscriberArgs } from '@medusajs/framework'
import { ECOMAIL_MODULE } from 'medusa-plugin-ecomail'
import type EcomailService from 'medusa-plugin-ecomail'
export default async function customerCreatedHandler({
event: { data },
container,
}: SubscriberArgs<{ id: string }>) {
const ecomailService = container.resolve<EcomailService>(ECOMAIL_MODULE)
const customerService = container.resolve('customerService')
const customer = await customerService.retrieve(data.id)
await ecomailService.addSubscriberToListIfNotAdded({
email: customer.email,
name: customer.first_name,
surname: customer.last_name,
})
}

Manual Sync from API Route

// Example: Custom API route for newsletter subscription
import { MedusaRequest, MedusaResponse } from '@medusajs/framework'
import { ECOMAIL_MODULE } from 'medusa-plugin-ecomail'
import type EcomailService from 'medusa-plugin-ecomail'
export async function POST(req: MedusaRequest, res: MedusaResponse) {
const ecomailService = req.scope.resolve<EcomailService>(ECOMAIL_MODULE)
const { email, name, surname } = req.body
await ecomailService.addSubscriberToListIfNotAdded({
email,
name,
surname,
})
res.json({ success: true })
}

TypeScript Types

type EcomailModuleOptions = {
ecomailListId: string
ecomailToken: string
shopDomain?: string
requireExplicitConsent?: boolean
consentMetadataKey?: string
}
type SubscriberDataT = {
email: string
name?: string
surname?: string
city?: string
country?: string
zip?: string
company?: string
street?: string
phone?: string
[key: string]: string | undefined
}

Testing

Default Mode (sync everyone):

  1. Configure plugin without Copy to clipboardrequireExplicitConsent or set it to Copy to clipboardfalse
  2. Place a test order
  3. Verify customer appears in Ecomail list
  4. Verify transaction is tracked

GDPR Mode (require consent):

  1. Configure plugin with Copy to clipboardrequireExplicitConsent: true
  2. Place order WITH consent (Copy to clipboardmetadata.ecomail_consent: true)
    • Customer should be synced βœ“
  3. Place order WITHOUT consent (Copy to clipboardmetadata.ecomail_consent: false)
    • Customer should NOT be synced βœ“
  4. Place order with NO metadata
    • Customer should NOT be synced βœ“

Testing via Admin Panel

The plugin includes an admin panel (Settings β†’ Ecomail) where you can:

  • Test adding subscribers manually
  • Check if a subscriber exists
  • Update subscriber information
  • Verify your Ecomail connection

Error Handling

The plugin is designed to be resilient:

  • Ecomail sync failures do not break the order flow
  • All errors are logged for debugging
  • Orders complete successfully even if Ecomail is unavailable

Development

# Build the plugin
yarn build
# Development mode with watch
yarn dev

Resources

License

MIT

Author

Gramino

Made with ❀️ for the Medusa community

You may also like

Browse all integrations

Build your own

Develop your own custom integraiton

Build your own integration with our API to speed up your processes. Make your integration available via npm for it to be shared in our Library with the broader Medusa community.

gift card interface

Ready to build your custom commerce setup?