medusa-plugin-brevo-email
Notifications plugin for Medusa ecommerce server that sends transactional emails via Brevo.
Features
- Uses the email templating features built into BREVO
- The plugin is in active development. If you have any feature requests, please open an issue.
- Create PDF invoices and credit notes and attach them to the email
- Send out upsell emails to customers that have recently placed an order with certain collections
- Send out automated abandoned cart emails to customers that have abandoned their cart (based on last updated date of cart)
- Support different languages base on countrycode or locale. (Need to add "locale or countryCode to cart context on frontend)
Configuration
Enable in your medusa-config.js file similar to other plugins:
More events? (work in progress within the plugin!) See here
Config example with multi language
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879const plugins = [// ... other plugins{resolve: `medusa-plugin-brevo-email`,options: {api_key: process.env.BREVO_API_KEY,from_email: process.env.BREVO_FROM_EMAIL,from_name: process.env.BREVO_FROM_NAME,// Event templates with countryCode and locale supportevents: {order: {placed: {en: process.env.BREVO_ORDER_PLACED_EN || 3,vn: process.env.BREVO_ORDER_PLACED_VN || 11, // Vietnamese templatedefault: process.env.BREVO_ORDER_PLACED || 3, // Fallback if neither countryCode nor locale match},canceled: {en: process.env.BREVO_ORDER_CANCELED_EN || 6,vn: process.env.BREVO_ORDER_CANCELED_VN || 14, // Vietnamese templatedefault: process.env.BREVO_ORDER_CANCELED || 6, // Fallback if neither countryCode nor locale match},shipment_created: {en: process.env.BREVO_ORDER_SHIPMENT_CREATED_EN || 4,vn: process.env.BREVO_ORDER_SHIPMENT_CREATED_VN || 10, // Vietnamese templatedefault: process.env.BREVO_ORDER_SHIPMENT_CREATED || 4, // Fallback if neither countryCode nor locale match},},customer: {created: {en: process.env.BREVO_CUSTOMER_CREATED_EN || 7,vn: process.env.BREVO_CUSTOMER_CREATED_VN || 12, // Vietnamese templatedefault: process.env.BREVO_CUSTOMER_CREATED || 7, // Fallback if neither countryCode nor locale match},password_reset: {en: process.env.BREVO_CUSTOMER_PASSWORD_RESET_EN || 5,vn: process.env.BREVO_CUSTOMER_PASSWORD_RESET_VN || 5, // Vietnamese templatedefault: process.env.BREVO_CUSTOMER_PASSWORD_RESET || 5, // Fallback if neither countryCode nor locale match},},user: {password_reset: {en: process.env.BREVO_USER_PASSWORD_RESET_EN || 5,vn: process.env.BREVO_USER_PASSWORD_RESET_VN || 5, // Vietnamese templatedefault: process.env.BREVO_USER_PASSWORD_RESET || 5, // Fallback if neither countryCode nor locale match},},},// Contact list settingscontact_list: {enabled: process.env.BREVO_CONTACT_LIST_ENABLED || true,contact_list_id: process.env.BREVO_CONTACT_LIST_ID || 2,},// Abandoned cart settings with locale and countryCode supportabandoned_cart: {enabled: process.env.BREVO_ABANDONED_CART_ENABLED || false,first: {delay: process.env.BREVO_ABANDONED_CART_FIRST_DELAY || 24, // Delay in hourstemplate: {en: process.env.BREVO_ABANDONED_CART_FIRST_TEMPLATE_EN || 2,vn: process.env.BREVO_ABANDONED_CART_FIRST_TEMPLATE_VN || 13, // Vietnamese templatedefault: process.env.BREVO_ABANDONED_CART_FIRST_TEMPLATE || 2, // Fallback if neither countryCode nor locale match},},second: {delay: process.env.BREVO_ABANDONED_CART_SECOND_DELAY || 72, // Delay in hourstemplate: {en: process.env.BREVO_ABANDONED_CART_SECOND_TEMPLATE_EN || 2,vn: process.env.BREVO_ABANDONED_CART_SECOND_TEMPLATE_VN || 13, // Vietnamese templatedefault: process.env.BREVO_ABANDONED_CART_SECOND_TEMPLATE || 2, // Fallback if neither countryCode nor locale match},},},},},]
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102const plugins = [// ... other plugins{resolve: `medusa-plugin-brevo-email`,options: {api_key: process.env.BREVO_API_KEY,from_email: process.env.BREVO_FROM_EMAIL,from_name: process.env.BREVO_FROM_NAME,bcc: process.env.BREVO_BCC || null,contact_list: {enabled: process.env.BREVO_CONTACT_LIST_ENABLED || true,contact_list_id: process.env.BREVO_CONTACT_LIST_ID || 2},pdf: {enabled: process.env.BREVO_PDF_ENABLED || false,settings: {font: process.env.BREVO_PDF_FONT || 'Helvetica',// [{file: 'yourfont.ttf', name: 'yourfont'},{file: 'yourfont-bold.ttf', name: 'yourfontbold'}]format: process.env.BREVO_PDF_FORMAT || 'A4',// see supported formats here: https://pdfkit.org/docs/paper_sizes.htmlmargin: {top: process.env.BREVO_PDF_MARGIN_TOP || '50',right: process.env.BREVO_PDF_MARGIN_RIGHT || '50',bottom: process.env.BREVO_PDF_MARGIN_BOTTOM || '50',left: process.env.BREVO_PDF_MARGIN_LEFT || '50'},empty: "" // what to show if variable can't be found. Defaults to __UNDEFINED__},header: {enabled: process.env.BREVO_PDF_HEADER_ENABLED || false,content: process.env.BREVO_PDF_HEADER_CONTENT || null,// loads empty header if null, otherwise loads the file from `BREVO_PDF_HEADER_CONTENT`height: process.env.BREVO_PDF_HEADER_HEIGHT || '50'},footer: {enabled: process.env.BREVO_PDF_FOOTER_ENABLED || false,content: process.env.BREVO_PDF_FOOTER_CONTENT || null,// loads empty footer if null, otherwise loads the file from `BREVO_PDF_FOOTER_CONTENT`},templates: {invoice: process.env.BREVO_PDF_INVOICE_TEMPLATE || null,credit_note: process.env.BREVO_PDF_CREDIT_NOTE_TEMPLATE || null,return_invoice: process.env.BREVO_PDF_RETURN_INVOICE_TEMPLATE || null}},events: {order: {placed: process.env.BREVO_ORDER_PLACED || null,canceled: process.env.BREVO_ORDER_CANCELED || null,shipment_created: process.env.BREVO_ORDER_SHIPMENT_CREATED || null,},customer: {created: process.env.BREVO_CUSTOMER_CREATED || null,password_reset: process.env.BREVO_CUSTOMER_PASSWORD_RESET || null,},user: {created: process.env.BREVO_USER_CREATED || null,password_reset: process.env.BREVO_USER_PASSWORD_RESET || null,},auth: {password_reset: process.env.BREVO_AUTH_PASSWORD_RESET || null,verify_account: process.env.BREVO_AUTH_VERIFY_ACCOUNT || null,},activity: {inactive_user: process.env.BREVO_ACTIVITY_INACTIVE_USER || null,inactive_customer: process.env.BREVO_ACTIVITY_INACTIVE_CUSTOMER || null,}},upsell: {enabled: process.env.BREVO_UPSELL_ENABLED || false,template: process.env.BREVO_UPSELL_TEMPLATE || null, // if you supply multiple templates (comma seperated), the plugin will pick one at randomdelay: process.env.BREVO_UPSELL_DELAY || 9, // delay in daysvalid: process.env.BREVO_UPSELL_VALID || 30, // valid in dayscollection: process.env.BREVO_UPSELL_COLLECTION || null,},abandoned_cart: {enabled: process.env.BREVO_ABANDONED_CART_ENABLED || false,first: {delay: process.env.BREVO_ABANDONED_CART_FIRST_DELAY || 1, // delay in hourstemplate: process.env.BREVO_ABANDONED_CART_FIRST_TEMPLATE || null, // if you supply multiple templates (comma seperated), the plugin will pick one at random},second: {delay: process.env.BREVO_ABANDONED_CART_SECOND_DELAY || 24, // delay in hourstemplate: process.env.BREVO_ABANDONED_CART_SECOND_TEMPLATE || null, // if you supply multiple templates (comma seperated), the plugin will pick one at random},third: {delay: process.env.BREVO_ABANDONED_CART_THIRD_DELAY || 48, // delay in hourstemplate: process.env.BREVO_ABANDONED_CART_THIRD_TEMPLATE || null, // if you supply multiple templates (comma seperated), the plugin will pick one at random},},default_data: {// ... default data to be passed to the email templateproduct_url: process.env.BREVO_PRODUCT_URL || '',product_name: process.env.BREVO_PRODUCT_NAME || '',company_name: process.env.BREVO_COMPANY_NAME || '',company_address: process.env.BREVO_COMPANY_ADDRESS || '',}}}]
Templates
The plugin uses the BREVO template system for emails. For attachments the plugin relies on the pdfkit library.
In your JSON templates you can use several types (and variables):
In your JSON templates you can use several types (and variables):
- Copy to clipboard
image
for (local) images - Copy to clipboard
text
for simple words, (long) sentences, paragraphs and links - Copy to clipboard
moveDown
for moving the cursor down one line - Copy to clipboard
hr
for a horizontal line - Copy to clipboard
tableRow
for a table(-like) row - Copy to clipboard
itemLoop
for looping over items in an order - Copy to clipboard
itemLoopEnd
for ending the item loop
Example:
1234567891011121314151617181920212223242526272829[{"type": "image","image": "image.png","x": 100,"y": 100,"fit": [200, 50]},{"type": "text","text": "This is a text","size": 20},{"type": "moveDown","lines": 2},{"type": "hr"},{"type": "moveDown","lines": 2},{"type": "text","text": "Another text"}]
image
Images are stored in Copy to clipboard
/src/images/
and can be used in the template like this:1234567{"type": "image","image": "image.png","x": 100,"y": 100,"fit": [200, 50]}
Copy to clipboard
fit
has multiple options, see here for more info.Optional:
- Copy to clipboard
align
horizontally align the image, the possible values are Copy to clipboardleft
, Copy to clipboardcenter
, or Copy to clipboardright
- Copy to clipboard
valign
vertically align the image, the possible values are Copy to clipboardtop
, Copy to clipboardcenter
, or Copy to clipboardbottom
text
Text can be used for words, sentences, paragraphs and links.
1234{"type": "text","text": "This is a text"}
If you use Copy to clipboard
moveDown
correct you won't need to use Copy to clipboardx
and Copy to clipboardy
for the text.Optional:
These options can be used to style the text or to position it.
- Copy to clipboard
x
the x position of the text - Copy to clipboard
y
the y position of the text - Copy to clipboard
font
the font of the text - Copy to clipboard
size
the font size of the text - Copy to clipboard
color
the color of the text (Hex codes Copy to clipboard#ff0000
) - Copy to clipboard
width
the width of the text - Copy to clipboard
align
the alignment of the text, the possible values are Copy to clipboardleft
, Copy to clipboardcenter
, Copy to clipboardright
, or Copy to clipboardjustify
.
For more styling options, see here for more info.
moveDown
This is used to move the cursor down one or more line(s).
1234{"type": "moveDown","lines": 1}
hr
This is used to draw a horizontal line.
123{"type": "hr"}
Optional:
- Copy to clipboard
color
the color of the line (Hex codes Copy to clipboard#ff0000
) - Copy to clipboard
width
the width of the line if you don't want it to be the full width of the page - Copy to clipboard
height
the height of the line element, including padding - Copy to clipboard
y
the y position of the line if you can not rely on the cursor (affected by Copy to clipboardmoveDown
)
tableRow
This is used to draw a table row.
12345678910111213{"type": "tableRow","columns": [{"text": "Column 1","width": 200},{"text": "Column 2","width": 150}]}
Optional:
You can use the same options as for Copy to clipboard
text
to style the text in the table row. If you want a special column styled, you can add the options to the column object.```
Acknowledgement
This plugin is originally based on medusa-plugin-postmark by Fullstack-nl.