# Integrating AcelleMail with WordPress and WooCommerce

> WordPress + WooCommerce is the most common stack people connect to AcelleMail. There's no first-class plugin — instead, you wire up the REST API from a few WordPress hooks. This guide walks the three integration patterns (user registration, WooCommerce purchase, optional unsubscribe sync) end-to-end, plus the choice of "API from theme/plugin" vs "embedded signup form" vs "third-party Zapier".

- Canonical URL: https://acellesend.com/kb/articles/integrating-acellemail-with-wordpress-and-woocommerce
- Author: Tom Becker, Developer Editor
- Category: Integrations — Stripe, PayPal, WordPress, WooCommerce, Zapier, webhooks, API
- Content type: tutorial · Difficulty: intermediate
- Tags: Acellemail
- Published: 2026-01-28 · Last updated: 2026-08-15
- Reading time: 9 min
- Publisher: AcelleMail Knowledge Base, https://acellesend.com/kb

---

## What this is for

WordPress + WooCommerce is the most common stack people connect to AcelleMail. There's **no first-class AcelleMail plugin** in the WordPress.org plugin directory — instead, you wire up the [REST API](https://acellesend.com/kb/articles/rest-api-authentication-and-endpoints) from a few WordPress hooks. The good news: it's ~30 lines of PHP and works reliably.

This guide is the **master overview** with all three integration patterns explained. Each pattern has a dedicated deep-dive article linked at the end.

## Three integration patterns

| Pattern | Use when | Code goes in |
|---|---|---|
| **User-register sync** | You want every WordPress account creation to add a subscriber | `functions.php` or a custom mu-plugin, hooking `user_register` |
| **WooCommerce purchase sync** | You want every paying customer added to a list (and possibly trigger automations) | Same place, hooking `woocommerce_order_status_completed` |
| **Embedded signup form** | You want a marketing-list signup form on a WP page (no PHP) | Paste AcelleMail's form embed code into a Custom HTML block |
| **Zapier** | You want point-and-click without writing PHP | See [Zapier Integration Guide](https://acellesend.com/kb/articles/zapier-integration-guide) |

Pick the one that matches your use case. Most stores end up using #2 + #3 together — purchase sync for paying customers + an embedded form for newsletter signups.

## Prerequisites (all patterns)

- A working AcelleMail install
- An AcelleMail API token — see [Getting Started with the REST API](https://acellesend.com/kb/articles/getting-started-with-the-acellemail-rest-api) Step 1
- An AcelleMail list (UID copied from **Lists → Overview → click the list → URL contains the UID**)
- WordPress 5.5+ (for the modern `wp_remote_post` reliability)

> **Field name gotcha:** AcelleMail's subscriber API uses **UPPERCASE** field names (`EMAIL`, `FIRST_NAME`, `LAST_NAME`, `MAIL_LIST_UID`) — not lowercase. Older guides get this wrong. The API accepts uppercase only.

## Pattern 1 — Sync on WordPress user registration

Detail in [WordPress Subscriber Sync](https://acellesend.com/kb/articles/wordpress-subscriber-sync). Summary:

```php
add_action('user_register', function ($user_id) {
    $user = get_user_by('id', $user_id);

    wp_remote_post('https://mail.example.com/api/v1/subscribers', [
        'headers' => [
            'Authorization' => 'Bearer ' . ACELLEMAIL_API_TOKEN,
            'Accept'        => 'application/json',
            'Content-Type'  => 'application/json',
        ],
        'body' => wp_json_encode([
            'MAIL_LIST_UID' => 'YOUR_LIST_UID',
            'EMAIL'         => $user->user_email,
            'FIRST_NAME'    => $user->first_name ?: '',
            'LAST_NAME'     => $user->last_name ?: '',
        ]),
        'timeout' => 10,
        'blocking' => false,   // fire and forget
    ]);
});
```

Define `ACELLEMAIL_API_TOKEN` in `wp-config.php` (not in the theme — credentials must not be in version control).

## Pattern 2 — Sync on WooCommerce purchase

Detail in [WooCommerce Post-Purchase Emails](https://acellesend.com/kb/articles/woocommerce-post-purchase-emails). Summary:

```php
add_action('woocommerce_order_status_completed', function ($order_id) {
    $order = wc_get_order($order_id);
    if (!$order) return;

    $tags = [];
    foreach ($order->get_items() as $item) {
        $cats = get_the_terms($item->get_product_id(), 'product_cat');
        if ($cats) foreach ($cats as $c) $tags[] = $c->slug;
    }

    wp_remote_post('https://mail.example.com/api/v1/subscribers', [
        'headers' => [
            'Authorization' => 'Bearer ' . ACELLEMAIL_API_TOKEN,
            'Accept'        => 'application/json',
            'Content-Type'  => 'application/json',
        ],
        'body' => wp_json_encode([
            'MAIL_LIST_UID' => 'POST_PURCHASE_LIST_UID',
            'EMAIL'         => $order->get_billing_email(),
            'FIRST_NAME'    => $order->get_billing_first_name(),
            'LAST_NAME'     => $order->get_billing_last_name(),
            'ORDER_TOTAL'   => $order->get_total(),
            'ORDER_ID'      => $order_id,
            'tags'          => implode(',', array_unique($tags)),
        ]),
        'timeout' => 10,
        'blocking' => false,
    ]);
});
```

This subscribes the customer to the "post-purchase" list with the order context. Configure an automation in AcelleMail to send a welcome → review-request → upsell sequence — see the [post-purchase emails article](https://acellesend.com/kb/articles/woocommerce-post-purchase-emails) for the 4-step sequence template.

## Pattern 3 — Embedded signup form

Inside AcelleMail:

1. **Lists → Your list → Forms → Create new**
2. Customize fields shown (email + first name is typical for newsletters)
3. **Copy embed code** — gives you either an `<iframe>` snippet or a JS-rendered snippet

In WordPress:

1. Edit the page where you want the form (homepage, footer widget, etc.)
2. Insert a **Custom HTML block**
3. Paste the embed code
4. Save → the form renders inline

**Trade-offs:** the embedded form posts directly to AcelleMail — no WordPress code needed, no API token needed. Downside: limited styling (iframe constraints) and no opportunity to add extra logic on submit. For a simple newsletter signup, it's perfect.

For more customisation, build your own HTML form that POSTs to `/api/v1/public/subscribers` (the unauthenticated endpoint — see [REST API reference](https://acellesend.com/kb/articles/rest-api-authentication-and-endpoints#public-unauthenticated)).

## Optional — sync unsubscribes back to WordPress

When a subscriber unsubscribes from your AcelleMail list, you may want to update WordPress user metadata (e.g. clear a `newsletter_subscribed` flag, set a "do not contact" tag).

**Two approaches:**

### A. Per-campaign webhook on `campaign.unsubscribe`

Configure an AcelleMail webhook (Campaign → Webhooks) on the `campaign.unsubscribe` event, pointing to a custom REST endpoint in WordPress:

```php
// In a plugin file
add_action('rest_api_init', function () {
    register_rest_route('acellemail/v1', '/unsubscribe', [
        'methods'  => 'POST',
        'callback' => function (\WP_REST_Request $req) {
            // Verify auth (Bearer token or shared header — match what you set in AcelleMail webhook config)
            $auth = $req->get_header('authorization');
            if ($auth !== 'Bearer ' . WEBHOOK_SHARED_SECRET) {
                return new \WP_REST_Response('Unauthorized', 401);
            }

            $email = $req->get_param('subscriber_email');
            $user = get_user_by('email', $email);
            if ($user) {
                update_user_meta($user->ID, 'newsletter_subscribed', '0');
            }

            return new \WP_REST_Response(['ok' => true], 200);
        },
        'permission_callback' => '__return_true',
    ]);
});
```

The endpoint is at `https://your-wp-site.com/wp-json/acellemail/v1/unsubscribe`. Configure that URL in the AcelleMail webhook config (per [webhook reference](https://acellesend.com/kb/articles/webhook-events-reference)).

### B. Periodic sync via REST API

Run a daily cron in WordPress that fetches the list's current unsubscribed subscribers via the API and updates user meta:

```php
add_action('acellemail_daily_sync', function () {
    $response = wp_remote_get(
        'https://mail.example.com/api/v1/subscribers?filter[list_uid]=YOUR_LIST_UID&filter[status]=unsubscribed&per_page=200',
        ['headers' => ['Authorization' => 'Bearer ' . ACELLEMAIL_API_TOKEN, 'Accept' => 'application/json']]
    );
    $data = json_decode(wp_remote_retrieve_body($response), true);
    foreach (($data['data'] ?? []) as $sub) {
        $user = get_user_by('email', $sub['email']);
        if ($user) update_user_meta($user->ID, 'newsletter_subscribed', '0');
    }
});

if (!wp_next_scheduled('acellemail_daily_sync')) {
    wp_schedule_event(time(), 'daily', 'acellemail_daily_sync');
}
```

Pattern A is real-time but more setup; Pattern B is simpler but lags up to 24 hours. Pick based on your urgency.

## Where to put the code

**Don't paste into `functions.php`** unless you're 100% comfortable losing it on a theme switch. Better:

```bash
# Create a custom mu-plugin (must-use; auto-loaded; survives any theme change)
sudo mkdir -p /path/to/wp-content/mu-plugins
sudo tee /path/to/wp-content/mu-plugins/acellemail-integration.php <<'EOF'
<?php
/**
 * Plugin Name: AcelleMail Integration
 * Description: Sync WordPress + WooCommerce users to AcelleMail
 */

if (!defined('ACELLEMAIL_API_TOKEN') || !defined('ACELLEMAIL_LIST_UID')) {
    return; // Skip if not configured (defined in wp-config.php)
}

// ... your add_action hooks here ...
EOF
```

Then in `wp-config.php`:

```php
define('ACELLEMAIL_API_TOKEN', 'your-token-here');
define('ACELLEMAIL_LIST_UID', 'your-list-uid');
```

## Testing the integration

```bash
# Tail Acelle's app log + WP debug log simultaneously
sudo tail -f /var/www/acellemail/storage/logs/laravel.log \
              /path/to/wp-content/debug.log

# Then in WordPress, register a test user OR place a test WC order
# You should see in Acelle's log: a subscribers.create API hit
# And in WP debug.log (if WP_DEBUG_LOG is on): the wp_remote_post response
```

If nothing happens:

- Verify `WP_DEBUG_LOG = true` is set in `wp-config.php` to see PHP errors
- Verify the API token works via curl (see [getting-started](https://acellesend.com/kb/articles/getting-started-with-the-acellemail-rest-api))
- Verify the `MAIL_LIST_UID` is the *list* UID, not the campaign UID (common confusion)

## Common issues

| What you see | Likely cause | Fix |
|---|---|---|
| Subscriber appears but field values are empty | Used lowercase field names (`email`, not `EMAIL`) | Switch to uppercase per the API spec |
| API returns 422 "MAIL_LIST_UID required" | Posted to `/lists/{uid}/subscribers` without the field, or posted to `/subscribers` without the field | Use `/api/v1/subscribers` + include `MAIL_LIST_UID` in the body |
| WordPress page loads slowly after adding the hook | Default `wp_remote_post` is blocking — adds 200-500ms per registration | Add `'blocking' => false` to make it fire-and-forget |
| Duplicate subscribers (1 in WP user, 1 in WooCommerce) | Both `user_register` AND `woocommerce_order_status_completed` fired for the same email | Acelle handles duplicates (upserts by email) — verify; or scope each hook to a different list |
| Embedded form doesn't render | iframe blocked by Content-Security-Policy | Add the AcelleMail domain to your CSP `frame-src`; or use the JS-rendered embed instead |
| `wp_remote_post` returns `WP_Error` "cURL error 60" | TLS verification failed (self-signed cert on dev install) | Use `['sslverify' => false]` for testing only; fix the cert before production |
| Unsubscribe webhook arrives but WP user not updated | `get_user_by('email')` returned null — email mismatch | Lowercase both sides before lookup (`strtolower($email)`) |

## FAQ

**Is there an official AcelleMail WordPress plugin?** Not on WordPress.org as of 2026. The hooks-based integration is the recommended pattern — small, transparent, no plugin-dependency risk.

**Can I import existing WordPress users into AcelleMail?** Yes — export the WP user list as CSV (via a plugin like User Import Export) and import into AcelleMail via **Lists → Your list → Subscribers → Import**. See [Importing Contacts](https://acellesend.com/kb/articles/importing-contacts-csv-best-practices-and-field-mapping).

**WooCommerce Subscriptions / Memberships?** Same approach — hook the relevant event (`woocommerce_subscription_status_active`, `wc_memberships_user_membership_status_changed`) and POST to the AcelleMail API. Read the WC documentation for the exact hook names.

**Can AcelleMail send transactional emails for WooCommerce (order confirmation, password reset)?** Yes via the [Amazon SES](https://acellesend.com/kb/articles/configuring-amazon-ses-with-acellemail) integration — both WooCommerce and AcelleMail can send through the same SES sending identity. Don't try to route WooCommerce transactional through AcelleMail's send-a-campaign API (wrong shape).

**Performance impact on WP site?** With `'blocking' => false` added, < 1ms overhead per user-register / order completion. Without it, 200-500ms — measurable on busy sites.

**Multi-site WordPress (WPMU)?** Same hooks work network-wide. Use `is_multisite() ? $blog_id : null` to differentiate, or scope per-blog to different AcelleMail lists.

**Can I push back to WordPress from AcelleMail?** Yes via webhooks — see the "Optional — sync unsubscribes back" section above.

## Related articles

- [WordPress Subscriber Sync](https://acellesend.com/kb/articles/wordpress-subscriber-sync) — Pattern 1 in detail
- [WooCommerce Post-Purchase Emails](https://acellesend.com/kb/articles/woocommerce-post-purchase-emails) — Pattern 2 + automation sequence
- [Getting Started with the AcelleMail REST API](https://acellesend.com/kb/articles/getting-started-with-the-acellemail-rest-api) — prerequisite
- [REST API Authentication and Endpoints](https://acellesend.com/kb/articles/rest-api-authentication-and-endpoints) — full endpoint reference
- [Webhook Events Reference](https://acellesend.com/kb/articles/webhook-events-reference) — for unsubscribe sync back to WP
- [Zapier Integration Guide](https://acellesend.com/kb/articles/zapier-integration-guide) — no-code alternative
- [Importing Contacts](https://acellesend.com/kb/articles/importing-contacts-csv-best-practices-and-field-mapping) — bulk-import existing WP users
- [Configuring Amazon SES with AcelleMail](https://acellesend.com/kb/articles/configuring-amazon-ses-with-acellemail) — shared sending stack
- [Post-Purchase Follow-up Automation](https://acellesend.com/kb/articles/post-purchase-follow-up-automation) — the automation template that consumes Pattern 2 events

---

## Related articles

- [Connecting Stripe for Subscription Billing](https://acellesend.com/kb/articles/connecting-stripe-for-subscription-billing): AcelleMail's Cashier ships Stripe as the first-class subscription gateway. This guide walks the connection end-to-end: API key configuration, the four webhook events that must be subscribed, the webhook URL location, and test-vs-live mode discipline. Covers both subscription billing (for SaaS operators) and one-off payment use cases.
- [WordPress Subscriber Sync](https://acellesend.com/kb/articles/wordpress-subscriber-sync): Wire up the WordPress user_register hook to push every new account into an AcelleMail list. Twenty lines of PHP, no plugin dependency, real-time. This guide covers the production-ready snippet (with timeout / async / error handling) and the four common gotchas — field-name case, secrets in version control, slow page loads, duplicate subscribers.
- [Zapier Integration Guide for AcelleMail](https://acellesend.com/kb/articles/zapier-integration-guide): AcelleMail doesn't ship a native Zapier app, but the REST API + webhook system gives you everything you need to wire AcelleMail to the 7,000+ apps on Zapier. This guide walks both directions — AcelleMail as a Zapier action (POST to API), and AcelleMail as a Zapier trigger (webhook → Zap). Plus 6 production-tested Zap recipes.
- [WooCommerce Post-Purchase Emails](https://acellesend.com/kb/articles/woocommerce-post-purchase-emails): The window right after a WooCommerce purchase is the highest-engagement moment a customer ever has with you. A well-timed thank-you / usage-tips / review-request / cross-sell sequence quietly increases LTV without any additional ad spend. This guide walks the hook setup, the 4-step sequence template, the product-category tagging trick, and the AcelleMail automation that ties it all together.
- [BIMI with VMC — Cost, Process, and Whether It's Worth It](https://acellesend.com/kb/articles/bimi-with-vmc-cost-walkthrough): VMC (Verified Mark Certificate) costs $1,500/yr per domain and takes 4-8 weeks to obtain. This guide walks the cost math, the trademark requirements, the alternative paths, and a decision framework for whether VMC is right for your sending program.
