Embed the Connector Widget¶
Use this guide when you need to let a user connect their store to Conflux from inside your own page — for example, inside a Rapidmail account page or an onboarding screen — without requiring them to visit the Conflux admin panel.
The connector widget (<conflux-connector>) handles the full connection lifecycle: it auto-creates a tenant on first load, lets the user generate a plugin pairing token, and emits events you can react to on the host page.
1. Load the widget script¶
Add the script tag before the custom element is used:
The script is a self-contained IIFE bundle with no external runtime dependencies. It registers the <conflux-connector> custom element and isolates its styles inside a shadow DOM, so it cannot be broken by the host page's CSS.
2. Place the element¶
Drop the element where the connection UI should appear:
<conflux-connector
system="rapidmail"
connection="woocommerce"
external-user-id="user_12345"
api-base="https://your-conflux-domain.com"
></conflux-connector>
On mount the widget calls POST /api/system-connections/connect to create a tenant and an active Rapidmail connection. The conflux-initialized event fires once that completes.
Props¶
| Prop | Required | Description |
|---|---|---|
system |
No | Slug of the embedding system (e.g. rapidmail). When supplied and the slug matches a known System record in Conflux, the widget creates an Active connection immediately and issues a never-expiring access token instead of a short-lived pairing token. |
connection |
No | Slug of the target e-commerce system (e.g. woocommerce). Controls the plugin installation steps shown to the user and the system badge colour in the header. |
external-user-id |
No | User identifier in the embedding platform (e.g. a Rapidmail account ID). Stored on the SystemConnection for later matching. |
api-base |
No | Base URL of the Conflux instance (e.g. https://conflux.example.com). Defaults to empty string (same-origin). Always set this when embedding on an external domain. |
tenant-id |
No | UUID of an existing tenant. Pass this on subsequent page loads (after conflux-initialized has fired once) to skip the auto-creation step. |
token |
No | Plaintext access token issued on a prior init. Pass alongside tenant-id on subsequent loads to skip the init API call entirely. |
lang |
No | BCP 47 language tag (e.g. en). Reserved for future i18n support; has no effect in the current build. |
Events¶
conflux-initialized¶
Fires once when the widget has created (or confirmed) a tenant and an Active connection to the embedding system (end of phase 1).
window.addEventListener('conflux-initialized', function (event) {
const { tenant_id, token } = event.detail;
// Persist both values server-side, keyed to the current user.
// Pass them back as the tenant-id and token props on subsequent loads
// so the widget skips the init step.
myApi.saveConfluxCredentials(tenant_id, token);
});
Detail shape:
Store both values against the user's account. The token is the never-expiring access token issued by Conflux; it is returned only once. On subsequent page loads, pass tenant-id and token as props so the widget can skip the init call.
conflux-registered¶
Fires when the user's e-commerce plugin confirms the connection — that is, when Conflux detects that the pending SystemConnection has transitioned to active.
window.addEventListener('conflux-registered', function (event) {
const { connection_id } = event.detail;
console.log('Plugin connected:', connection_id);
// Enable sync features for this user.
});
Detail shape:
Both events bubble through the shadow DOM boundary (bubbles: true, composed: true), so a single listener on window (or any ancestor element) can receive them regardless of where the widget is placed. They are dispatched from the <conflux-connector> host element itself, so attaching a listener directly to the element also works.
Full example¶
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Connect your store</title>
</head>
<body>
<conflux-connector
system="rapidmail"
connection="woocommerce"
external-user-id="<?= esc_attr($currentUser->id) ?>"
api-base="https://conflux.example.com"
></conflux-connector>
<script src="https://conflux.example.com/connector-widget.js" defer></script>
<script>
window.addEventListener('conflux-initialized', function (event) {
fetch('/my-app/api/conflux-credentials', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(event.detail),
});
});
window.addEventListener('conflux-registered', function (event) {
document.getElementById('sync-panel').hidden = false;
});
</script>
</body>
</html>
Returning users¶
On first load, emit conflux-initialized and persist tenant_id and token. On all subsequent loads, pass them back so the widget skips the init call:
<!-- Subsequent loads — pass credentials stored from the first visit -->
<conflux-connector
system="rapidmail"
connection="woocommerce"
external-user-id="user_12345"
tenant-id="{{ $user->conflux_tenant_id }}"
token="{{ $user->conflux_token }}"
api-base="https://conflux.example.com"
></conflux-connector>
When both tenant-id and token are present, the widget skips the init call and goes directly to the connection step.
Building the widget¶
The widget is pre-built and committed to public/connector-widget.js. You only need to rebuild when you change a source file under resources/widget-connector/ (including plugin-urls.js):
The bundle is an IIFE with no external runtime dependencies and does not include Vue as a separate chunk.
Troubleshooting¶
The widget shows "Could not reach the Conflux server."
A network or CORS error prevented the init request. Confirm api-base is correct and that the Conflux instance allows cross-origin requests from your domain.
conflux-initialized fires but token in the detail is null.
The system prop did not match a known System slug in Conflux. Only a matching system triggers the Active connection and access token path. For the Rapidmail use case, confirm the SystemSeeder has been run and that system="rapidmail" is spelled correctly.
conflux-registered never fires.
The plugin has not called back yet. The widget polls GET /api/widget/connections/{id}/status every 3 seconds. If the plugin's token has been pasted correctly, the event fires as soon as Conflux sees the status change to active.
See also¶
- Connector Widget — how the two-phase flow and access tokens work
- Embed the Configuration Widget — how to embed
<conflux-config>once the connection is established - Connection Flow — the broader registration handshake context