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 an 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. It loads its font files (Inter) from the same Conflux instance, under /widget-assets/. Load the script directly from the Conflux instance with a classic <script src> as shown, because the font URLs are resolved relative to the script's own URL; a copied, self-hosted, inlined or type="module" script cannot find the fonts and the widget falls back to the system font.
If the host page sends a Content Security Policy, allow that origin for fonts, for example font-src https://your-conflux-domain.com. Without it the browser blocks the fonts and the widget falls back to the system font.
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 |
Yes | Slug of the embedding system (e.g. rapidmail). When 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. Omitting it is rejected client-side and by the API. |
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 |
Yes | User identifier in the embedding platform (e.g. a Rapidmail account ID). Stored on the SystemConnection for later matching. Omitting it is rejected client-side and by the API. |
api-base |
No | Base URL of the Conflux instance (e.g. https://conflux.example.com). Defaults to https://conflux.me (production). Override with https://staging.conflux.me or a local URL when embedding elsewhere. |
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. Supported: en, fr, pl, de, es, it. Any other value (or an unset prop) falls back to en. Controls the language of all widget copy — see Connector Widget → Localisation. |
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 built from the sources under resources/widget-connector/; the output is not committed. Build it after cloning and whenever you change a source file there (including plugin-urls.js):
The build writes public/connector-widget.js, an IIFE that does not include Vue as a separate chunk, and the Inter fonts to public/widget-assets/.
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.
The widget shows an error immediately, with no network request in the browser devtools.
system or external-user-id is missing from the element. Both are required — the widget checks for them before calling the API and shows this error without making a request. The API rejects the same condition with a 422 if the check is ever bypassed.
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.
Widget copy stays in English despite a lang prop.
Only en, fr, pl, de, es, it have translations. Any other BCP 47 tag silently falls back to English rather than erroring.
The widget renders in the system font instead of Inter.
The font files under /widget-assets/ could not be used. Open the browser's Network tab and check the status of the font request first. A 404 means the font files are missing from public/widget-assets/: the widgets were not built or deployed, or a cached older widget script asks for a hash that no longer exists. A 200 without an Access-Control-Allow-Origin header means the server does not send that header for /widget-assets/ (see ADR-0040). A Content Security Policy error means the host page's font-src does not allow the Conflux origin.
See also¶
- Connector Widget — how the two-phase flow and access tokens work
- Update Connector Widget Translations — add or change a translated string or locale
- Embed the Configuration Widget — how to embed
<conflux-config>once the connection is established - Connection Flow — the broader registration handshake context