The [Lumail WordPress plugin](https://github.com/Melvynx/lumail-opensource/tree/main/wordpress) renders `[lumail_form]` and upserts contacts with `POST /api/v2/subscribers`. The browser only talks to `admin-ajax.php`. The `lum_` token never leaves the WordPress server.

Requires WordPress 6.2+ and PHP 8.0+. Source: [github.com/Melvynx/lumail-opensource](https://github.com/Melvynx/lumail-opensource) (`wordpress/`).

## How it works

1. A visitor submits the form.
2. JavaScript `POST`s to `admin-ajax.php` (`lumail_subscribe`) with a nonce.
3. WordPress sanitizes the email, applies a honeypot and a one-minute rate limit, then calls Lumail:

```
POST https://lumail.io/api/v2/subscribers
Authorization: Bearer lum_…
```

| Field | Value |
| --- | --- |
| `email` | Required |
| `name` | Optional, if the name field is shown |
| `tags` | Default tags from Settings, merged with shortcode `tags` |
| `skipDoubleOptIn` | `false` — org double opt-in still applies |
| `resubscribe` | `false` — `UNSUBSCRIBED` contacts stay unsubscribed |
| `triggerWorkflows` | `true` |
| `ipAddress` | Visitor IP (Cloudflare `CF-Connecting-IP` when present) |

There is no Gutenberg block and no WooCommerce sync. For checkout or other trusted backends, use the [Create Subscriber API](/docs/api-reference/v2/subscribers-create) with `skipDoubleOptIn: true`.

## Install

```bash
git clone https://github.com/Melvynx/lumail-opensource.git
cp -R lumail-opensource/wordpress /path/to/wp-content/plugins/lumail
```

The plugin folder **must** be named `lumail` (it loads `lumail.php`). Then:

1. wp-admin → **Plugins** → activate **Lumail**
2. **Settings → Lumail**

## API token

Create a token with the **`subscribers`** permission:

1. Lumail → **Settings → API Tokens** (or follow [Create an API Token](/docs/tutorials/create-api-token))
2. Name it `WordPress` and pick the **App** preset, or a custom set that includes `subscribers`
3. Copy the `lum_…` secret once
4. Paste it in WordPress **Settings → Lumail**. Leave the field blank on later saves to keep the current token

The settings screen only shows `lum_…` plus the last four characters. **Test connection** is `GET /api/v2/subscribers?limit=1` — a 200 means the token can read subscribers.

Optional: set **Default tags** (`wordpress, newsletter`). They merge with tags on the shortcode.

## Shortcode

Put this on a page or post:

```
[lumail_form]
```

| Attribute | Default | Meaning |
| --- | --- | --- |
| `title` | empty | Heading above the fields |
| `button` | Settings button label (`Subscribe`) | Submit label |
| `show_name` | Settings checkbox | `true` / `false` |
| `tags` | empty | Extra tags, comma-separated, merged with defaults |

```
[lumail_form title="Get the newsletter" tags="blog" button="Join" show_name="true"]
```

Success copy comes from **Settings → Lumail → Success message**. With double opt-in on, keep it something like “Check your inbox to confirm.”

## Double opt-in and unsubscribes

The plugin is a **public form**. It never sends `skipDoubleOptIn: true` and never resubscribes.

- Org double opt-in on → new contacts are `PENDING_CONFIRMATION` and get the confirmation email. See [Enable Double Opt-In](/docs/tutorials/enable-double-opt-in).
- Someone already `UNSUBSCRIBED` stays unsubscribed. They do not re-enter the list from this form.
- Tag-triggered workflows still fire for new confirmed (or immediately subscribed) contacts.

## Troubleshooting

| Symptom | Check |
| --- | --- |
| “Lumail is not configured correctly.” | Token missing, not `lum_…`, or lacks `subscribers`. Save, then Test connection. |
| “Enter a valid email.” | Client-side or `sanitize_email` rejected the address. |
| “Wait a minute before trying again.” | One submit per email+IP per minute. |
| Form submits but nobody appears | Double opt-in: look under **Subscribers → Pending Confirmation**. |
| Unsubscribed contact does not come back | Expected. `resubscribe` is off. Use Lumail (or the API with `resubscribe: true`) if you mean to bring them back. |

A filled honeypot field (`website`) returns the same success message and does not call Lumail.

## Related

- [Create Subscriber](/docs/api-reference/v2/subscribers-create)
- [Create an API Token](/docs/tutorials/create-api-token)
- [Enable Double Opt-In](/docs/tutorials/enable-double-opt-in)
- Plugin source and how it is built: [wordpress/](https://github.com/Melvynx/lumail-opensource/tree/main/wordpress)
