CMS & Site Builders

Add email to your content site in minutes — from member welcome flows to post-published notifications.

Machine translation available — choose your language in the top bar.

Each adapter maps a CMS lifecycle event to a Mailgrid POST /api/emails call. The two environment variables every integration shares:

VariableRequiredDescription
MAILGRID_KEYYesYour mb_live_… API key from the contact form.
MAILGRID_FROMYesVerified sending address, e.g. hello@yourdomain.com.

WordPress

The WordPress integration is a drop-in plugin located at integrations/wordpress/mailgrid.php. It hooks into WordPress via the pre_wp_mail filter to replace wp_mail() entirely — every email your site sends, including password resets, comment notifications, and custom plugin mail, routes through Mailgrid without any code changes to themes or other plugins.

Setup

  1. Upload integrations/wordpress/mailgrid.php to wp-content/plugins/mailgrid/ on your server (or zip the folder and use Plugins → Add New → Upload).
  2. Activate the plugin from WP Admin → Plugins.
  3. Go to Settings → Mailgrid and enter your API key and verified from-address.
  4. Send a test email via the settings page to confirm delivery.

How it hooks in

mailgrid.php
add_filter( 'pre_wp_mail', 'mailgrid_intercept_wp_mail', 10, 2 );

function mailgrid_intercept_wp_mail( $return, array $atts ): bool {
    $api_key = get_option( 'mailgrid_api_key' );
    $from    = get_option( 'mailgrid_from_address' );

    if ( empty( $api_key ) ) {
        return null; // fall through to wp_mail
    }

    $to      = (array) $atts['to'];
    $subject = $atts['subject'] ?? '';
    $message = $atts['message'] ?? '';
    $headers = $atts['headers'] ?? [];

    $is_html = mailgrid_headers_have_html( $headers );

    wp_remote_post( 'https://api.mailgrid.space/api/emails', [
        'headers' => [
            'Authorization' => 'Bearer ' . $api_key,
            'Content-Type'  => 'application/json',
        ],
        'body' => wp_json_encode([
            'from'    => $from,
            'to'      => $to,
            'subject' => $subject,
            $is_html ? 'html' : 'text' => $message,
        ]),
    ] );

    return true; // short-circuit native wp_mail
}
WooCommerce

A WooCommerce-specific extension is available that hooks into WC_Email at the transport layer and maps order templates to Mailgrid template IDs. See the E-commerce docs for details.

Environment variables

VariableRequiredDescription
MAILGRID_API_KEYYesStored in wp_options as mailgrid_api_key; can also be defined in wp-config.php via define('MAILGRID_API_KEY', '...').
MAILGRID_FROM_ADDRESSYesOverrides the WordPress "from" address for all outgoing mail.
MAILGRID_STREAM_IDNoRoute all WordPress mail through a named Mailgrid stream.
MAILGRID_TRACK_OPENSNoSet to 1 to inject an open-tracking pixel. Default: 0.

Webflow

Webflow does not expose server-side code, so the integration is a Cloudflare Worker located at integrations/webflow/. When a visitor submits any Webflow form, the Worker receives the form_submission webhook, creates an InboxOS contact via the Mailgrid contacts API, and fires a welcome email. No backend code required on your Webflow site.

Setup

  1. Deploy the Worker:
    terminal
    cd integrations/webflow
    npm install
    npx wrangler secret put MAILGRID_KEY
    npx wrangler deploy
  2. In your Webflow project, open Site Settings → Integrations → Form Webhook.
  3. Paste your Worker URL (e.g. https://mailgrid-webflow.your-subdomain.workers.dev/webhook) into the webhook field and save.
  4. Publish your Webflow site. Every subsequent form submission will trigger the Worker.

Key configuration

src/worker.mjs
export default {
  async fetch(request, env) {
    const { data, name } = await request.json();
    // data.fields is a key/value map of form field names to submitted values
    const email     = data.fields.find(f => f.name === 'email')?.value;
    const firstName = data.fields.find(f => f.name === 'name')?.value ?? '';

    if (!email) return new Response('ok');

    // 1. Create / upsert InboxOS contact
    await fetch('https://api.mailgrid.space/api/contacts', {
      method:  'POST',
      headers: {
        'Authorization': `Bearer ${env.MAILGRID_KEY}`,
        'Content-Type':  'application/json',
      },
      body: JSON.stringify({ email, firstName, source: `webflow-form:${name}` }),
    });

    // 2. Send welcome email
    await fetch('https://api.mailgrid.space/api/emails', {
      method:  'POST',
      headers: {
        'Authorization': `Bearer ${env.MAILGRID_KEY}`,
        'Content-Type':  'application/json',
      },
      body: JSON.stringify({
        from:       env.MAILGRID_FROM,
        to:         email,
        templateId: env.MAILGRID_WELCOME_TEMPLATE,
        variables:  { firstName },
      }),
    });

    return new Response('ok');
  }
};

Environment variables

VariableRequiredDescription
MAILGRID_KEYYesMailgrid API key, set as a Wrangler secret.
MAILGRID_FROMYesVerified sender address for welcome emails.
MAILGRID_WELCOME_TEMPLATENoMailgrid template ID for the welcome email. Falls back to a plain-text body if omitted.
MAILGRID_STREAM_IDNoRoute form-submission mail through a named Mailgrid stream.

Ghost

The Ghost integration is a Cloudflare Worker at integrations/ghost/ that combines Ghost webhook events with the Ghost Admin API. On member.created it sends a welcome email to the new member. On post.published it paginates the full Ghost member list and dispatches a newsletter batch to all active subscribers via Mailgrid.

Setup

  1. Deploy the Worker:
    terminal
    cd integrations/ghost
    npm install
    npx wrangler secret put MAILGRID_KEY
    npx wrangler secret put GHOST_ADMIN_API_KEY
    npx wrangler deploy
  2. Register the webhooks against your Ghost instance using the included script:
    ghost.mjs (register-webhook)
    import GhostAdminAPI from '@tryghost/admin-api';
    
    const api = new GhostAdminAPI({
      url:     process.env.GHOST_URL,
      key:     process.env.GHOST_ADMIN_API_KEY,
      version: 'v5.0',
    });
    
    for (const event of ['member.created', 'post.published']) {
      await api.webhooks.add({
        event,
        target_url: `${process.env.WORKER_URL}/webhooks/ghost`,
      });
      console.log(`registered: ${event}`);
    }

Key configuration

src/worker.mjs
import { fetchAllMembers, batchSend } from './ghost.mjs';

export default {
  async fetch(request, env) {
    const { event, data } = await request.json();

    if (event === 'member.created') {
      await fetch('https://api.mailgrid.space/api/emails', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${env.MAILGRID_KEY}`,
          'Content-Type':  'application/json',
        },
        body: JSON.stringify({
          from:       env.MAILGRID_FROM,
          to:         data.member.current.email,
          templateId: env.MAILGRID_WELCOME_TEMPLATE,
          variables:  { name: data.member.current.name },
        }),
      });
    }

    if (event === 'post.published') {
      // paginate all active Ghost subscribers
      const members = await fetchAllMembers(env.GHOST_URL, env.GHOST_ADMIN_API_KEY);
      await batchSend(members, data.post.current, env);
    }

    return new Response('ok');
  }
};

Environment variables

VariableRequiredDescription
MAILGRID_KEYYesMailgrid API key, set as a Wrangler secret.
MAILGRID_FROMYesVerified sender address for all Ghost-triggered mail.
GHOST_URLYesYour Ghost instance URL, e.g. https://blog.yourdomain.com.
GHOST_ADMIN_API_KEYYesAdmin API key from Ghost Admin → Integrations → Add custom integration.
WORKER_URLYesPublic URL of the deployed Worker for webhook registration.
MAILGRID_WELCOME_TEMPLATENoTemplate ID for member.created welcome emails.
MAILGRID_NEWSLETTER_TEMPLATENoTemplate ID for post.published newsletter sends.
MAILGRID_STREAM_IDNoRoute Ghost mail through a dedicated Mailgrid stream.

Supported events

Contentful

The Contentful integration is a Cloudflare Worker at integrations/contentful/. It listens for Contentful Content Management API webhooks filtered to Entry.publish events on the blogPost content type. On publish it sends an author notification and, optionally, a newsletter to your subscriber list.

Setup

  1. Deploy the Worker:
    terminal
    cd integrations/contentful
    npm install
    npx wrangler secret put MAILGRID_KEY
    npx wrangler secret put CONTENTFUL_WEBHOOK_SECRET
    npx wrangler deploy
  2. Register the webhook using the included script:
    register-webhook.mjs
    import { createClient } from 'contentful-management';
    
    const client = createClient({ accessToken: process.env.CONTENTFUL_MGMT_TOKEN });
    const space  = await client.getSpace(process.env.CONTENTFUL_SPACE_ID);
    
    await space.createWebhookWithId('mailgrid-webhook', {
      name:   'Mailgrid CMS notifications',
      url:    `${process.env.WORKER_URL}/webhooks/contentful`,
      topics: ['Entry.publish'],
      filters: [{
        equals: [{ doc: 'sys.contentType.sys.id' }, 'blogPost'],
      }],
      headers: [{
        key:    'x-webhook-secret',
        value:  process.env.CONTENTFUL_WEBHOOK_SECRET,
        secret: true,
      }],
    });
    console.log('Contentful webhook registered');

Key configuration

src/worker.mjs
export default {
  async fetch(request, env) {
    const secret = request.headers.get('x-webhook-secret');
    if (secret !== env.CONTENTFUL_WEBHOOK_SECRET) {
      return new Response('Forbidden', { status: 401 });
    }

    const entry = await request.json();
    const title  = entry.fields.title?.en?.trim() ?? 'New post';
    const author = entry.fields.authorEmail?.en;
    const slug   = entry.fields.slug?.en;

    // 1. Author notification
    if (author) {
      await mailgridSend({
        to: author, subject: `Published: ${title}`,
        templateId: env.MAILGRID_AUTHOR_TEMPLATE,
        variables: { title, slug },
      }, env);
    }

    // 2. Subscriber newsletter
    if (env.SUBSCRIBER_LIST_ID) {
      await sendNewsletter({ title, slug, env });
    }

    return new Response('ok');
  }
};

Environment variables

VariableRequiredDescription
MAILGRID_KEYYesMailgrid API key, set as a Wrangler secret.
MAILGRID_FROMYesVerified sender address.
CONTENTFUL_WEBHOOK_SECRETYesShared secret sent as x-webhook-secret header for request verification.
CONTENTFUL_MGMT_TOKENYes (register)Contentful management token used by register-webhook.mjs only.
CONTENTFUL_SPACE_IDYes (register)Contentful space ID used by register-webhook.mjs only.
MAILGRID_AUTHOR_TEMPLATENoTemplate ID for author publish notifications.
SUBSCRIBER_LIST_IDNoMailgrid list ID; when set, a newsletter is sent to all list subscribers on publish.
WORKER_URLYes (register)Deployed Worker URL, used by the registration script.

Strapi

The Strapi integration lives at integrations/strapi/ and ships as two pieces: an email provider plugin that wires Mailgrid into Strapi's @strapi/plugin-email provider slot, and lifecycle hook examples for triggering custom sends on content events. It is a drop-in replacement for Strapi's built-in email — any existing call to strapi.plugins.email.services.email.send() routes through Mailgrid automatically.

Setup

  1. Copy the provider into your Strapi project:
    terminal
    cp -r integrations/strapi/providers/strapi-provider-email-mailgrid \
           src/providers/
  2. Configure the provider in config/plugins.js:
    config/plugins.js
    module.exports = ({ env }) => ({
      email: {
        config: {
          provider:        './providers/strapi-provider-email-mailgrid',
          providerOptions: {
            apiKey: env('MAILGRID_KEY'),
          },
          settings: {
            defaultFrom:    env('MAILGRID_FROM'),
            defaultReplyTo: env('MAILGRID_FROM'),
          },
        },
      },
    });
  3. Add lifecycle hooks in src/api/[collection]/content-types/[collection]/lifecycles.js for custom event emails (see example below).

Key configuration

src/providers/strapi-provider-email-mailgrid/index.js
'use strict';

module.exports = {
  async init(providerOptions) {
    return {
      async send(options) {
        const { from, to, subject, html, text, templateId, variables } = options;
        const res = await fetch('https://api.mailgrid.space/api/emails', {
          method:  'POST',
          headers: {
            'Authorization': `Bearer ${providerOptions.apiKey}`,
            'Content-Type':  'application/json',
          },
          body: JSON.stringify({ from, to, subject, html, text, templateId, variables }),
        });
        if (!res.ok) {
          throw new Error(`Mailgrid send failed: ${res.status}`);
        }
      },
    };
  },
};

Environment variables

VariableRequiredDescription
MAILGRID_KEYYesMailgrid API key, read via env('MAILGRID_KEY') in config/plugins.js.
MAILGRID_FROMYesDefault from-address for all Strapi email.
MAILGRID_STREAM_IDNoNamed Mailgrid stream; pass as streamId in the provider options.

Directus

The Directus integration at integrations/directus/ consists of two parts: a Hook extension that fires on item lifecycle events (create, update), and a custom Flow Operation called Send via Mailgrid that can be wired into any Directus Flow using the visual editor. A custom REST endpoint is also included for manual trigger sends from external systems.

Setup

  1. Copy the extension bundle into your Directus extensions directory:
    terminal
    cp -r integrations/directus/extensions/mailgrid \
           extensions/hooks/mailgrid
    cp -r integrations/directus/extensions/mailgrid-operation \
           extensions/operations/mailgrid-operation
  2. Add the required env vars to your Directus .env (see table below).
  3. Restart Directus. The hook activates automatically; the Flow operation appears under Flows → Operations → Mailgrid: Send Email.
  4. In the Directus Flows UI, create or edit a Flow, add a trigger (e.g. Event Hook → items.create), then chain the Send via Mailgrid operation. Map fields from the trigger payload to the operation inputs using Directus's {{item.field}} syntax.

Key configuration

extensions/hooks/mailgrid/index.js
export default ({ action }, { env, services, database }) => {
  const { ItemsService } = services;

  action('users.create', async ({ key, payload }) => {
    const email = payload.email;
    if (!email) return;

    await fetch('https://api.mailgrid.space/api/emails', {
      method:  'POST',
      headers: {
        'Authorization': `Bearer ${env.MAILGRID_KEY}`,
        'Content-Type':  'application/json',
      },
      body: JSON.stringify({
        from:       env.MAILGRID_FROM,
        to:         email,
        templateId: env.MAILGRID_WELCOME_TEMPLATE,
        variables:  { firstName: payload.first_name },
      }),
    });
  });
};

Environment variables

VariableRequiredDescription
MAILGRID_KEYYesMailgrid API key, added to Directus .env and accessed via env.MAILGRID_KEY inside extensions.
MAILGRID_FROMYesVerified sender address.
MAILGRID_WELCOME_TEMPLATENoTemplate ID for user welcome email fired on users.create.
MAILGRID_STREAM_IDNoRoute Directus mail through a named Mailgrid stream.

Supported events

Sanity

The Sanity integration is a Cloudflare Worker at integrations/sanity/ that receives GROQ-powered webhooks from Sanity Studio. A GROQ filter restricts delivery to specific document type transitions (e.g. article documents moving to published status), keeping noise low. The register-webhook.mjs script sets up the webhook via the Sanity API.

Setup

  1. Deploy the Worker:
    terminal
    cd integrations/sanity
    npm install
    npx wrangler secret put MAILGRID_KEY
    npx wrangler secret put SANITY_WEBHOOK_SECRET
    npx wrangler deploy
  2. Register the webhook with your Sanity project:
    register-webhook.mjs
    import { createClient } from '@sanity/client';
    
    const client = createClient({
      projectId: process.env.SANITY_PROJECT_ID,
      dataset:   process.env.SANITY_DATASET ?? 'production',
      token:     process.env.SANITY_API_TOKEN,
      apiVersion: '2024-01-01',
      useCdn:    false,
    });
    
    await client.request({
      uri:    `/hooks/projects/${process.env.SANITY_PROJECT_ID}`,
      method: 'POST',
      body: {
        type:   'document',
        rule:   { on: 'update' },
        filter: '_type == "article" && status == "published"',
        url:    `${process.env.WORKER_URL}/webhooks/sanity`,
        secret: process.env.SANITY_WEBHOOK_SECRET,
      },
    });
    console.log('Sanity webhook registered');

Key configuration

src/worker.mjs
import { isValidSignature, SIGNATURE_HEADER_NAME } from '@sanity/webhook';

export default {
  async fetch(request, env) {
    const body      = await request.text();
    const signature = request.headers.get(SIGNATURE_HEADER_NAME);

    if (!isValidSignature(body, signature, env.SANITY_WEBHOOK_SECRET)) {
      return new Response('Forbidden', { status: 401 });
    }

    const doc = JSON.parse(body);

    await fetch('https://api.mailgrid.space/api/emails', {
      method:  'POST',
      headers: {
        'Authorization': `Bearer ${env.MAILGRID_KEY}`,
        'Content-Type':  'application/json',
      },
      body: JSON.stringify({
        from:       env.MAILGRID_FROM,
        to:         env.NOTIFY_EMAIL,
        templateId: env.MAILGRID_PUBLISH_TEMPLATE,
        variables:  { title: doc.title, slug: doc.slug?.current },
      }),
    });

    return new Response('ok');
  }
};

Environment variables

VariableRequiredDescription
MAILGRID_KEYYesMailgrid API key, set as a Wrangler secret.
MAILGRID_FROMYesVerified sender address.
SANITY_WEBHOOK_SECRETYesSecret used to verify the sanity-webhook-signature header.
SANITY_PROJECT_IDYes (register)Sanity project ID, used by register-webhook.mjs.
SANITY_API_TOKENYes (register)Sanity API token with Editor or higher role for webhook registration.
NOTIFY_EMAILYesEmail address to notify on document publish (can be a distribution list).
MAILGRID_PUBLISH_TEMPLATENoTemplate ID for publish notifications.
WORKER_URLYes (register)Deployed Worker URL used by the registration script.

Supported events

Wix

The Wix integration uses Wix Velo backend modules located at integrations/wix/. Copy the files into your Wix Editor's Velo backend section to handle CRM and store events. Velo backend modules run server-side on Wix's infrastructure and have access to secrets stored in the Wix Secrets Manager.

Setup

  1. In Wix Editor, enable Velo Dev Mode from the top menu.
  2. Open the Backend tab in the file tree and copy the module files from integrations/wix/backend/:
    Wix Editor → Velo → Backend
    # Files to copy into Wix Backend panel:
    mailgrid.js          # API client helper
    events.js            # CRM + store event handlers
  3. In Wix Secrets Manager (Dev Tools → Secrets Manager), add secrets named MAILGRID_KEY and MAILGRID_FROM.
  4. Publish your Wix site. Event handlers fire automatically on the next eligible event.

Key configuration

backend/events.js
import { getSecret } from 'wix-secrets-backend';
import { sendViaMailgrid } from 'backend/mailgrid';

// Fires when a CRM contact is created (e.g. form submit, checkout)
export async function wixCrm_onContactCreated(event) {
  const apiKey = await getSecret('MAILGRID_KEY');
  const from   = await getSecret('MAILGRID_FROM');
  const email  = event.contact?.primaryInfo?.email;

  if (!email) return;

  await sendViaMailgrid({
    apiKey, from, to: email,
    subject:    'Welcome!',
    templateId: 'WELCOME_TEMPLATE_ID',
    variables:  { firstName: event.contact?.name?.first },
  });
}

// Fires when a Wix Stores order is placed
export async function wixStores_onNewOrder(event) {
  const apiKey = await getSecret('MAILGRID_KEY');
  const from   = await getSecret('MAILGRID_FROM');
  const order  = event.order;
  const email  = order?.buyerInfo?.email;

  if (!email) return;

  await sendViaMailgrid({
    apiKey, from, to: email,
    subject:    `Order #${order._id} confirmed`,
    templateId: 'ORDER_TEMPLATE_ID',
    variables:  {
      orderId:    order._id,
      firstName:  order?.buyerInfo?.firstName,
      total:      order?.totals?.total,
    },
  });
}

Environment variables

Secret nameRequiredDescription
MAILGRID_KEYYesStored in Wix Secrets Manager; retrieved at runtime via getSecret('MAILGRID_KEY').
MAILGRID_FROMYesVerified sender address, stored as a Wix secret.

Supported events

Template IDs

All integrations accept an optional templateId that references a Mailgrid template. When omitted, the integration falls back to sending the inline html or text body you pass. Swap to a template at any time by setting the relevant env var — no code changes required. See Templates for how to create and manage them.

Webhook security

Every Cloudflare Worker integration verifies the platform's webhook signature before processing the payload. Never expose your Worker URL without this check in place — an unverified endpoint can be spoofed to trigger unwanted sends.