Back to Plugins

Postmark Notification Plugin

Comprehensive Postmark email integration for Medusa with PDF attachments, templates, upsell campaigns, and abandoned cart recovery


Overview

The medusa-plugin-postmark is a comprehensive notification plugin for Medusa that sends transactional emails through Postmark’s service. This plugin provides advanced features including email templating, PDF attachment generation, upsell campaigns, and abandoned cart recovery sequences.

Key Features

System Requirements

Before installing the plugin, ensure your system meets the following requirements:

Installation

Install the plugin using your preferred package manager:

# Using npm
npm install medusa-plugin-postmark

Configuration

Add the plugin to your medusa-config.js:

const plugins = [
  {
    resolve: `medusa-plugin-postmark`,
    options: {
      server_api: process.env.POSTMARK_SERVER_API,
      from: process.env.POSTMARK_FROM,
      bcc: process.env.POSTMARK_BCC || null,
      pdf: {
        enabled: process.env.POSTMARK_PDF_ENABLED || false,
        settings: {
          font: process.env.POSTMARK_PDF_FONT || 'Helvetica',
          format: process.env.POSTMARK_PDF_FORMAT || 'A4',
          margin: { top: '50', right: '50', bottom: '50', left: '50' },
          empty: ""
        },
        header: { enabled: false, content: null, height: '50' },
        footer: { enabled: false, content: null },
        templates: {
          invoice: process.env.POSTMARK_PDF_INVOICE_TEMPLATE || null,
          credit_note: process.env.POSTMARK_PDF_CREDIT_NOTE_TEMPLATE || null,
          return_invoice: process.env.POSTMARK_PDF_RETURN_INVOICE_TEMPLATE || null
        }
      },
      events: {
        order: {
          placed: process.env.POSTMARK_ORDER_PLACED || null,
          canceled: process.env.POSTMARK_ORDER_CANCELED || null,
          shipment_created: process.env.POSTMARK_ORDER_SHIPMENT_CREATED || null
        },
        customer: {
          created: process.env.POSTMARK_CUSTOMER_CREATED || null,
          password_reset: process.env.POSTMARK_CUSTOMER_PASSWORD_RESET || null
        },
        user: {
          created: process.env.POSTMARK_USER_CREATED || null,
          password_reset: process.env.POSTMARK_USER_PASSWORD_RESET || null
        },
        auth: {
          password_reset: process.env.POSTMARK_AUTH_PASSWORD_RESET || null,
          verify_account: process.env.POSTMARK_AUTH_VERIFY_ACCOUNT || null
        },
        activity: {
          inactive_user: process.env.POSTMARK_ACTIVITY_INACTIVE_USER || null,
          inactive_customer: process.env.POSTMARK_ACTIVITY_INACTIVE_CUSTOMER || null
        }
      },
      upsell: {
        enabled: process.env.POSTMARK_UPSELL_ENABLED || false,
        template: process.env.POSTMARK_UPSELL_TEMPLATE || null,
        delay: process.env.POSTMARK_UPSELL_DELAY || 9,
        valid: process.env.POSTMARK_UPSELL_VALID || 30,
        collection: process.env.POSTMARK_UPSELL_COLLECTION || null
      },
      abandoned_cart: {
        enabled: process.env.POSTMARK_ABANDONED_CART_ENABLED || false,
        first: { delay: 1, template: null },
        second: { delay: 24, template: null },
        third: { delay: 48, template: null }
      },
      default_data: {
        product_url: process.env.POSTMARK_PRODUCT_URL || '',
        product_name: process.env.POSTMARK_PRODUCT_NAME || '',
        company_name: process.env.POSTMARK_COMPANY_NAME || '',
        company_address: process.env.POSTMARK_COMPANY_ADDRESS || ''
      }
    }
  }
]

Environment Variables

Add the following to your .env file:

# Required
POSTMARK_SERVER_API=your_postmark_api_key
POSTMARK_FROM=noreply@yourdomain.com

# Optional
POSTMARK_BCC=admin@yourdomain.com

# PDF Settings
POSTMARK_PDF_ENABLED=true
POSTMARK_PDF_FONT=Helvetica
POSTMARK_PDF_FORMAT=A4

# Event Templates (Postmark Template IDs)
POSTMARK_ORDER_PLACED=1234567
POSTMARK_ORDER_CANCELED=1234568
POSTMARK_CUSTOMER_CREATED=1234569

# Upsell Campaign
POSTMARK_UPSELL_ENABLED=true
POSTMARK_UPSELL_TEMPLATE=1234570
POSTMARK_UPSELL_DELAY=9
POSTMARK_UPSELL_COLLECTION=collection_id

# Abandoned Cart
POSTMARK_ABANDONED_CART_ENABLED=true

# Company Info
POSTMARK_COMPANY_NAME=Your Company Name
POSTMARK_COMPANY_ADDRESS=123 Main St, City, State
POSTMARK_PRODUCT_URL=https://yourstore.com

PDF Template System

Templates use JSON structure with pdfkit for document generation. Six primary element types available:

Image Element

Place local images in /src/images/:

{
  "type": "image",
  "image": "image.png",
  "x": 100,
  "y": 100,
  "fit": [200, 50]
}

Text Element

{
  "type": "text",
  "text": "Sample content",
  "size": 12,
  "color": "#000000",
  "align": "left"
}

MoveDown Element

{
  "type": "moveDown",
  "lines": 2
}

HR Element

{
  "type": "hr",
  "color": "#cccccc"
}

Table Row

{
  "type": "tableRow",
  "columns": [
    { "text": "Header 1", "width": 200 },
    { "text": "Header 2", "width": 150 }
  ]
}

Item Loops

{ "type": "itemLoop" }

Template Variables

Access dynamic data using {{ variable_name }} syntax. Nested properties work: {{ order.customer.first_name }}.

Variable Functions

Dates:

{{ order.placed_at | date('en-US',{'year': 'numeric', 'month': 'long', 'day': 'numeric'}) }}

Currency:

{{ order.total_price | currency('en-US') }}

Country codes:

{{ order.shipping_address.country_code | country }}

Conditional Statements

{{ if variable }}
  Content to show if true
{{ endif }}

{{ if not variable }}
  Content to show if false
{{ endif }}

Multi-Language Support

Define templates per language in configuration:

events: {
  order: {
    placed: { nl: 1234, en: 1235 }
  }
}

Abandoned Cart Recovery

Configure a three-stage abandoned cart email sequence:

abandoned_cart: {
  enabled: true,
  first: { delay: 1, template: 'template_id_1' },    // 1 hour
  second: { delay: 24, template: 'template_id_2' },  // 24 hours
  third: { delay: 48, template: 'template_id_3' }    // 48 hours
}

Upsell Campaigns

Target customers with product recommendations:

upsell: {
  enabled: true,
  template: 'upsell_template_id',
  delay: 9,              // Days after purchase
  valid: 30,             // Campaign validity in days
  collection: 'col_id'   // Product collection to promote
}

Explore More Medusa Plugins

Find more powerful plugins and integrations to enhance your Medusa store. Browse our collection of community-driven solutions.

Free & Open Source
Community Driven
Easy Integration