How It Works
The Email Marketing plugin automatically syncs contacts to external providers when platform events occur.
Event-Driven Sync
The plugin hooks into two platform events:
User Registration
When a new user registers:
- Plugin captures the
user.registeredevent - Extracts user details (name, email, user type)
- Calls
syncContact()with tags:user_type:<type>,source:xilancer - Contact is pushed to all enabled providers
Order Payment
When an order is paid:
- Plugin captures the
order.paidevent - Extracts client (buyer) details
- Calls
syncContact()with tags:source:xilancer,event:order_paid - Contact is pushed to all enabled providers
Sync Process
Platform Event (registration/order)
│
▼
EmailMarketingPlugin hook handler
│
▼
syncContact() — iterates enabled providers
│
├──▶ MailchimpProvider::subscribe()
├──▶ SendGridProvider::subscribe()
├──▶ BrevoProvider::subscribe()
├──▶ ... (all enabled providers)
│
▼
Each makes HTTP call to provider API
Failures logged, never break platform flow
Contact Data
Each synced contact includes:
| Field | Source |
|---|---|
email | User's email address |
first_name | User's first name |
last_name | User's last name |
tags | Array of tags for segmentation |
Tags Applied
source:xilancer— All contactsuser_type:clientoruser_type:freelancer— Registration eventsevent:order_paid— Order payment eventstest-connection— Test subscriptions
Fire-and-Forget Design
Contact pushes are non-blocking:
- Platform events (registration, order) complete immediately
- Provider API calls happen asynchronously
- Failures are logged via
report()but never interrupt user flow - No retry mechanism for failed API calls
Data Flow
No Local Storage
The plugin does NOT store contacts locally:
- No database migrations
- No local contact table
- All data goes directly to external providers
- Plugin configuration stored in
static_optionstable
Provider Fan-Out
A single event can push to all 10 providers simultaneously:
- Each provider receives the same contact data
- Each provider handles the data according to their API
- Failures in one provider don't affect others
Limitations
- No unsubscribe — Only subscribe operations supported
- No webhooks — No inbound bounce/complaint handling
- No retry — Failed API calls are logged once
- Synchronous HTTP — 30-second timeout per provider
- Test contacts — Test endpoint creates real contacts in provider accounts
Last updated: September 2026
Still stuck?
Our support team is ready to help you get set up.

