diff --git a/docs/journeys/embedding.md b/docs/journeys/embedding.md index d1bdea2..746c568 100644 --- a/docs/journeys/embedding.md +++ b/docs/journeys/embedding.md @@ -44,46 +44,98 @@ The `DataInjectionOptions` type below defines all available options. See the [Em ```typescript title="DataInjectionOptions" export type DataInjectionOptions = { - /** the initial step index of the journey. aka, where to start the journey from */ + /** the stable id of the step to start the journey from. aka, where to start the journey from (recommended) */ + initialStepId?: string + /** + * the initial step index of the journey. + * @deprecated legacy alternative to initialStepId; the 0-based index shifts when steps are reordered + */ initialStepIndex?: number /** - * the initial state of the journey. aka, what data to prefill the journey with - * Read section below to understand how to populate this + * the initial state of the journey. aka, what data to prefill the journey with. + * Read section below to understand how to populate this. Two forms are supported: + * - recommended: an object keyed by the block's stable, journey-wide id -> block value + * - deprecated (legacy): an array indexed by step position, each entry keyed by block name * */ - initialState?: Record[] + initialState?: + | Record> + | Record[] /** the display options to be passed to the journey, for now it is used to disable some fields */ blocksDisplaySettings?: BlockDisplaySetting[] } + +export type BlockDisplaySetting = { + type: 'DISABLED' + /** the stable, journey-wide id of the block to target (recommended) */ + blockId?: string + /** @deprecated legacy alternative to blockId; the block name breaks silently when the block is renamed */ + blockName?: string + /** @deprecated legacy alternative to blockId; the 0-based step index shifts when steps are reordered */ + stepIndex?: number + blockFields?: string[] +} ``` -To populate `initialState` in `DataInjectionOptions` properly, open the journey in **debug mode** (see video below) and copy the journey state per step. +The **recommended** form keys `initialState` by **block ID** — the block's stable, journey-wide identifier. Block IDs are unique across the whole journey and are unaffected by block renames or by reordering steps, so an embed keyed by block ID keeps working even after the journey is restructured. To find a block's ID, open the block configurator in the Journey builder. + +A complete example combines all three: start the journey at a step by its stable `initialStepId`, prefill `initialState` keyed by block ID, and disable a block by `blockId`. Pass `dataInjectionOptions` alongside the rest of the options in `__epilot.init()`: + +```typescript title="Init with data injection by block ID" +__epilot.init([ + { + journeyId: '123', + mode: 'full-screen', + dataInjectionOptions: { + initialStepId: 'f0e1d2c3-b4a5-6789-0abc-def012345678', + initialState: { + 'b1f2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d': { city: 'Berlin' }, + }, + blocksDisplaySettings: [ + { + type: 'DISABLED', + blockId: 'b1f2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d', + blockFields: ['city'], + }, + ], + }, + }, +]) +``` -![Journey Embed Mode](../../static/img/journey-debug-mode.gif) +With the block-ID form you only list the blocks you actually want to prefill — there is no need to pad earlier steps with empty objects, and the mapping is unaffected by block renames or step reordering. To find a block's ID, open the block configurator in the Journey builder. -**Note**: `initialState` must be filled sequentially based on the order of steps; steps that are not injected into must be an **empty object**. -See example below to inject data into Step 2 and Step 3. Notice that Step 1 needs to be empty for this to work properly +### Data Injection builder (preview) -```typescript title="Injecting data into Steps 2 and 3" - initialState: [ - {}, - { - "Binary Input": false, - }, - { - "Personal Data Input": { - "salutation": "Ms. / Mrs.", - "firstName": "Test Name", - "lastName": "", - "email": "", - "telephone": "", - "_isValid": false - } +You don't have to hand-write block IDs. The Journey Builder includes a **Data Injection (preview)** tool that lets you build the configuration visually: pick the blocks and fields to prefill, set their pre-fill values, mark blocks as read-only, choose the starting step, then copy the generated snippet straight into your `__epilot.init()` call. + +![Data injection preview builder](../../static/img/data-injection-demo.gif) + +:::note Legacy step-index form (deprecated) + +The earlier array form of `initialState` (one entry per step indexed by **step position**, keyed by block **name**, with empty `{}` objects for steps you don't prefill) and the `blockName` + `stepIndex` form of `blocksDisplaySettings` are **deprecated but still supported** for backward compatibility. They break silently when blocks are renamed or steps are reordered, so prefer the block-ID form for new integrations. + +```typescript title="Injecting data by step index + block name (deprecated)" +initialState: [ + {}, + { + 'Binary Input': false, + }, + { + 'Personal Data Input': { + salutation: 'Ms. / Mrs.', + firstName: 'Test Name', + _isValid: false, }, - {} - ] -} + }, +] ``` +Open your Journey in **debug mode** from the Journey Builder and inspect the state for each step. See below: + +![Journey Embed Mode](../../static/img/journey-debug-mode.gif) + +::: + ## Configuration Possibilities For more advanced configuration options, you can modify the embed script yourself, as it adds an interface to your website to interact with the journey: `__epilot` @@ -143,6 +195,8 @@ type OptionsInit = { __epilot.init([{ journeyId: '123', mode: 'full-screen', topBar: false }]) ``` +To prefill data, pass `dataInjectionOptions` keyed by block ID alongside the rest of the options. See [Journey Data Injection](#journey-data-injection) for the full example and option reference. + ### update **Description** @@ -350,3 +404,9 @@ For new integrations, use the [Journey Embed SDK](/docs/journeys/sdk). It replac - The [`` Web Component](/docs/journeys/web-components) — renders directly in your page using Shadow DOM for better performance, accessibility, and tighter host integration. See the [SDK documentation](/docs/journeys/sdk) for setup, the full API reference, and a migration guide from `__epilot.init()`. + +## Changelog + +### 2026-06-11 + +- Data injection now documents stable **block IDs** as the recommended form: `initialState` keyed by block ID, `initialStepId` for the starting step, and `blocksDisplaySettings` targeting blocks by `blockId`. Block IDs are unique journey-wide and resilient to block renames and step reordering. The legacy step-index + block-name forms remain supported but are deprecated. diff --git a/docs/journeys/sdk.md b/docs/journeys/sdk.md index eb8877f..db51ec0 100644 --- a/docs/journeys/sdk.md +++ b/docs/journeys/sdk.md @@ -495,56 +495,81 @@ The `.dataInjectionOptions()` method accepts a `DataInjectionOptions` object wit ```typescript title="DataInjectionOptions" type DataInjectionOptions = { - /** The step index to start the Journey from (0-based) */ + /** The stable id of the step to start the Journey from (recommended) */ + initialStepId?: string + /** + * The step index to start the Journey from (0-based). + * @deprecated Legacy alternative to initialStepId; the index shifts when steps are reordered + */ initialStepIndex?: number - /** Pre-fill data for each step */ - initialState?: Record[] + /** + * Pre-fill data. Two forms are supported: + * - recommended: an object keyed by stable block id -> block value + * - deprecated (legacy): an array indexed by step position, each entry keyed by block name + */ + initialState?: + | Record> + | Record[] /** Control which blocks/fields are disabled */ blocksDisplaySettings?: BlockDisplaySetting[] } type BlockDisplaySetting = { type: 'DISABLED' - blockName: string - stepIndex: number + /** The stable, journey-wide id of the block to target (recommended) */ + blockId?: string + /** @deprecated Legacy alternative to blockId; breaks silently when the block is renamed */ + blockName?: string + /** @deprecated Legacy alternative to blockId; the 0-based step index shifts when steps are reordered */ + stepIndex?: number blockFields?: string[] } ``` ### Setting data injection options -Pass the object inline in your embed chain: +The **recommended** form keys `initialState` by **block ID** — the block's stable, journey-wide identifier. Block IDs are unique across the whole Journey and are unaffected by block renames or by reordering steps, so an embed keyed by block ID keeps working even after the Journey is restructured. -```html title="Pre-filling journey data" -
+Pass the object inline in your embed chain. The complete example below combines all three features in a single call — start the Journey at a step by its stable `initialStepId`, prefill `initialState` keyed by block id, and disable a block by `blockId`: - + .append('#target') ``` -You can combine all three features (a starting step, pre-filled state, and disabled fields) in a single call: +The same `.dataInjectionOptions({ ... })` call works with either backend — swap `.asIframe()` for `.asWebComponent()` to prefill a web component embed. -```javascript title="Setting data injection dynamically" +### Populating `initialState` + +The recommended form keys `initialState` by **block ID**. Each entry is an object of the field values for that block. Because the state is keyed by block ID, you only list the blocks you actually want to prefill — no per-step ordering or empty `{}` placeholders are needed, and the mapping is unaffected by block renames or step reordering. To find a block's ID, open the block configurator in the Journey builder. + +### Data Injection Options builder + +You don't have to hand-write block IDs. The Journey Builder includes a **Data Injection (preview)** tool that lets you build the configuration visually: pick the blocks and fields to prefill, set their pre-fill values, mark blocks as read-only, choose the starting step, then copy the generated options straight into your `.dataInjectionOptions()` call. + +![Data injection preview builder](../../static/img/data-injection-demo.gif) + +:::note Legacy step-index form (deprecated) + +`initialState` also accepts an array form (one entry per step indexed by **step position**, keyed by block **name**, with empty `{}` objects for steps you don't prefill), and `blocksDisplaySettings` also accepts the `blockName` + `stepIndex` pair. Both legacy forms are **deprecated but still supported** for backward compatibility; they break silently when blocks are renamed or steps are reordered, so prefer the block-ID form for new integrations. + +```javascript title="Legacy array form (deprecated)" $epilot .embed('') .asWebComponent() @@ -572,17 +597,12 @@ $epilot .append('#embed-target') ``` -### Populating `initialState` - -`initialState` is an array where each element corresponds to a Journey step (by index). Each step entry is an object keyed by block name, containing the field values for that block. - -- Steps that should not be pre-filled must be empty objects `{}`. -- The array must be ordered sequentially to match step order. - -To discover the correct block names and field structure, open your Journey in **debug mode** from the Journey Builder and inspect the state for each step. See below: +Open your Journey in **debug mode** from the Journey Builder and inspect the state for each step. See below: ![Journey Embed Mode](../../static/img/journey-debug-mode.gif) +::: + ## Events The SDK dispatches the same events as the Web Component, on the `window` object using `postMessage`. Listen for them with `window.addEventListener`: @@ -760,3 +780,9 @@ Some `OptionsInit` fields from the legacy script have no SDK equivalent: - `journeyUrl`: not supported. The SDK derives the iframe URL from `baseUrl`; pass it via `new Epilot({ baseUrl })` if you need a non-default Journey app. > The legacy `name` option **is** supported as `.name(value)`, which sets the iframe's `name` and `title`, or the web component's `title`. + +## Changelog + +### 2026-06-11 + +- Data injection now documents stable **block IDs** as the recommended form: `.dataInjectionOptions()` accepts `initialState` keyed by block ID, `initialStepId` for the starting step, and `blocksDisplaySettings` targeting blocks by `blockId`. Block IDs are unique journey-wide and resilient to block renames and step reordering. The legacy step-index + block-name forms remain supported but are deprecated. diff --git a/docs/journeys/web-components.md b/docs/journeys/web-components.md index 2d87cf1..fceb846 100644 --- a/docs/journeys/web-components.md +++ b/docs/journeys/web-components.md @@ -64,21 +64,21 @@ The Journey will render inline on your page. Read on for the full attribute refe All attributes are set as standard HTML attributes on the `` element. Boolean attributes accept `"true"` or `"false"` as string values. -| Attribute | Type | Default | Description | -| ------------------------ | ----------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `journey-id` | `string` | — | **Required.** The ID of the Journey to render. | -| `mode` | `"inline"` \| `"full-screen"` | `"full-screen"` | The display mode. `inline` renders the Journey within the page flow. `full-screen` renders it as an overlay. | -| `lang` | `"de"` \| `"en"` \| `"fr"` | `"de"` | Overrides the UI language. This affects UI labels and copy, but does not automatically translate static content configured in the Journey Builder. | -| `top-bar` | `"true"` \| `"false"` | `"true"` | Whether to show the top navigation bar. Only applies in `inline` mode — in `full-screen` mode the top bar is always visible and cannot be hidden. | -| `scroll-to-top` | `"true"` \| `"false"` | `"true"` | Whether to scroll the page to the top of the Journey when the user navigates to a new step. | -| `close-button` | `"true"` \| `"false"` | `"true"` | Whether to show the close button in the top bar. | -| `context-data` | JSON string | — | Additional contextual data passed to the Journey and included with the submission. Must be a JSON-encoded string of key-value pairs. See [Context Data](#context-data). | -| `data-injection-options` | JSON string | — | Pre-fill Journey fields and control the starting step. Must be a JSON-encoded string. See [Data Injection](#data-injection). | -| `journey-token` | `string` | — | A JWT token used for [post-qualification Journeys](./post-qualification.md). | +| Attribute | Type | Default | Description | +| ------------------------ | ----------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `journey-id` | `string` | — | **Required.** The ID of the Journey to render. | +| `mode` | `"inline"` \| `"full-screen"` | `"full-screen"` | The display mode. `inline` renders the Journey within the page flow. `full-screen` renders it as an overlay. | +| `lang` | `"de"` \| `"en"` \| `"fr"` | `"de"` | Overrides the UI language. This affects UI labels and copy, but does not automatically translate static content configured in the Journey Builder. | +| `top-bar` | `"true"` \| `"false"` | `"true"` | Whether to show the top navigation bar. Only applies in `inline` mode — in `full-screen` mode the top bar is always visible and cannot be hidden. | +| `scroll-to-top` | `"true"` \| `"false"` | `"true"` | Whether to scroll the page to the top of the Journey when the user navigates to a new step. | +| `close-button` | `"true"` \| `"false"` | `"true"` | Whether to show the close button in the top bar. | +| `context-data` | JSON string | — | Additional contextual data passed to the Journey and included with the submission. Must be a JSON-encoded string of key-value pairs. See [Context Data](#context-data). | +| `data-injection-options` | JSON string | — | Pre-fill Journey fields and control the starting step. Must be a JSON-encoded string. See [Data Injection](#data-injection). | +| `journey-token` | `string` | — | A JWT token used for [post-qualification Journeys](./post-qualification.md). | | `as-organization-id` | `string` | — | Organization ID to use as the Journey's organization context. Sent as the `x-epilot-org-id` header on entity requests. Useful in partner / shared-entities scenarios where the Journey needs to access data owned by a different organization. | -| `is-full-screen-entered` | `"true"` \| `"false"` | `"false"` | Controls whether a full-screen Journey is visible. Set to `"true"` to open it. Only applies when `mode` is `"full-screen"`. | -| `is-embedded` | `"true"` \| `"false"` | `"false"` | Indicates the Journey is embedded on a host app. | -| `debug` | `"true"` \| `"false"` | `"false"` | Enables debug mode for development and troubleshooting. | +| `is-full-screen-entered` | `"true"` \| `"false"` | `"false"` | Controls whether a full-screen Journey is visible. Set to `"true"` to open it. Only applies when `mode` is `"full-screen"`. | +| `is-embedded` | `"true"` \| `"false"` | `"false"` | Indicates the Journey is embedded on a host app. | +| `debug` | `"true"` \| `"false"` | `"false"` | Enables debug mode for development and troubleshooting. | :::tip Accessible name @@ -178,58 +178,107 @@ The `data-injection-options` attribute accepts a **JSON string** with the follow ```typescript title="DataInjectionOptions" type DataInjectionOptions = { - /** The step index to start the Journey from (0-based) */ + /** The stable id of the step to start the Journey from (recommended) */ + initialStepId?: string + /** + * The step index to start the Journey from (0-based). + * @deprecated Legacy alternative to initialStepId; the index shifts when steps are reordered + */ initialStepIndex?: number - /** Pre-fill data for each step */ - initialState?: Record[] + /** + * Pre-fill data. Two forms are supported: + * - recommended: an object keyed by stable block id -> block value + * - deprecated (legacy): an array indexed by step position, each entry keyed by block name + */ + initialState?: + | Record> + | Record[] /** Control which blocks/fields are disabled */ blocksDisplaySettings?: BlockDisplaySetting[] } type BlockDisplaySetting = { type: 'DISABLED' - blockName: string - stepIndex: number + /** The stable, journey-wide id of the block to target (recommended) */ + blockId?: string + /** @deprecated Legacy alternative to blockId; breaks silently when the block is renamed */ + blockName?: string + /** @deprecated Legacy alternative to blockId; the 0-based step index shifts when steps are reordered */ + stepIndex?: number blockFields?: string[] } ``` ### Setting data injection options -Pass the JSON directly as a string attribute using single quotes around the attribute value: +The **recommended** form keys `initialState` by **block ID** — the block's stable, journey-wide identifier. Block IDs are unique across the whole Journey and are unaffected by block renames or by reordering steps, so an embed keyed by block ID keeps working even after the Journey is restructured. + +Pass the JSON directly as a string attribute using single quotes around the attribute value. The complete example below starts the Journey at a step by its stable `initialStepId`, prefills a block by id via `initialState`, and disables that block's field by `blockId`: ```html title="Pre-filling journey data" ``` -You can also set it dynamically via JavaScript: +You can also set it dynamically via JavaScript, building the same options with `JSON.stringify`: ```javascript title="Setting data injection dynamically" const el = document.querySelector('epilot-journey') +el.setAttribute( + 'data-injection-options', + JSON.stringify({ + initialStepId: 'f0e1d2c3-b4a5-6789-0abc-def012345678', + initialState: { + 'b1f2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d': { city: 'Berlin' }, + }, + blocksDisplaySettings: [ + { + type: 'DISABLED', + blockId: 'b1f2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d', + blockFields: ['city'], + }, + ], + }) +) +``` + +### Populating `initialState` + +The recommended form keys `initialState` by **block ID**. Each entry is an object of the field values for that block. Because the state is keyed by block ID, you only list the blocks you actually want to prefill — no per-step ordering or empty `{}` placeholders are needed, and the mapping is unaffected by block renames or step reordering. + +### Data Injection builder (preview) + +You don't have to hand-write block IDs. The Journey Builder includes a **Data Injection (preview)** tool that lets you build the configuration visually: pick the blocks and fields to prefill, set their pre-fill values, mark blocks as read-only, choose the starting step, then copy the generated `data-injection-options` snippet straight onto your `` element. + +![Data injection preview builder](../../static/img/data-injection-demo.gif) + +:::note Legacy step-index form (deprecated) + +`initialState` also accepts an array form (one entry per step indexed by **step position**, keyed by block **name**, with empty `{}` objects for steps you don't prefill), and `blocksDisplaySettings` also accepts the `blockName` + `stepIndex` pair. Both legacy forms are **deprecated but still supported** for backward compatibility; they break silently when blocks are renamed or steps are reordered, so prefer the block-ID form for new integrations. + +```javascript title="Legacy array form (deprecated)" el.setAttribute( 'data-injection-options', JSON.stringify({ initialStepIndex: 1, initialState: [ + {}, { 'Product Selection': { selectedProduct: 'solar-panel-basic', _isValid: true, }, }, - {}, - {}, ], blocksDisplaySettings: [ { type: 'DISABLED', blockName: 'Product Selection', - stepIndex: 0, + stepIndex: 1, blockFields: ['selectedProduct'], }, ], @@ -237,16 +286,10 @@ el.setAttribute( ) ``` -### Populating `initialState` - -`initialState` is an array where each element corresponds to a Journey step (by index). Each step entry is an object keyed by block name, containing the field values for that block. - -- Steps that should not be pre-filled must be empty objects `{}`. -- The array must be ordered sequentially to match step order. - -To discover the correct block names and field structure, open your Journey in **debug mode** from the Journey Builder and inspect the state for each step. See below: +Open your Journey in **debug mode** from the Journey Builder and inspect the state for each step. See below: ![Journey Embed Mode](../../static/img/journey-debug-mode.gif) +::: ## Dynamic Attribute Updates @@ -431,3 +474,9 @@ If you are currently embedding Journeys using iframes with the `__epilot` embed 4. **Update CSP rules** — the same epilot domain rules apply. See [Content-Security-Policy](./content-security-policy.md). The attribute names on the Web Component map directly to the options you previously passed to `__epilot.init()`, converted to kebab-case (e.g. `topBar` becomes `top-bar`, `scrollToTop` becomes `scroll-to-top`). + +## Changelog + +### 2026-06-11 + +- Data injection now documents stable **block IDs** as the recommended form: `initialState` is keyed by block ID, `initialStepId` selects the starting step, and `blocksDisplaySettings` targets blocks by `blockId`. Block IDs are unique journey-wide and resilient to block renames and step reordering. The legacy step-index + block-name forms remain supported but are deprecated. diff --git a/static/img/data-injection-demo.gif b/static/img/data-injection-demo.gif new file mode 100644 index 0000000..a8b18b2 Binary files /dev/null and b/static/img/data-injection-demo.gif differ