Use this guide when an app uses experience.js analytics, privacy, preview, insights, or third-party plugin packages and you need to replace them with Optimization SDK Suite surfaces.
Legacy plugin packages are not one-for-one target packages. Privacy moves to app-owned consent plus SDK consent inputs. Vendor analytics moves to event-stream forwarding or app-owned business events. Preview moves to the Optimization preview panel attached to the live Web SDK. Insights delivery is part of the target SDK event and interaction model.
Use this after at least one target runtime guide is in place.
Gather these inputs:
@ninetailed/experience.js-plugin-* package and plugin constructor.window.ninetailed.plugins, window.ninetailed.consent, or preview globals.List each plugin by purpose, not by package name:
Then search for globals. Target SDK code should not depend on window.ninetailed, plugin globals,
or __nt-consent__.
The legacy privacy plugin stored consent and filtered events, traits, properties, profile merging, and features. In the target SDK, the app owns the consent record and passes the current decision to the SDK. Event consent and persistence consent are separate axes.
Use the runtime guide's consent section to decide:
onEventBlocked or states.blockedEventStream.Use the exact runtime section for the app: Web consent, React Web consent, App Router consent, or Pages Router consent.
Do not expect blocked legacy payloads to replay after consent changes. Re-emit application events that still need to happen under the accepted policy.
Replace vendor plugins with the
analytics forwarding guide.
Subscribe to accepted event streams in stateful browser runtimes and use request-local event results
on server runtimes. Dedupe accepted events by messageId, and forward only approved primitive
fields. states.eventStream carries accepted events; states.blockedEventStream carries only
consent-blocked diagnostics. onEventBlocked receives the same blocked diagnostic as a callback,
which is useful when you want logging without a browser-state subscription.
Keep vendor consent separate from SDK consent. SDK consent controls SDK event emission; your app's analytics policy controls whether data leaves your application boundary for a vendor.
Use the Optimization preview panel for Web and React Web based runtimes. The panel attaches to the
live Web SDK, reads audience and experience definitions from a Contentful client or pre-fetched
entries, and applies preview overrides to selected optimizations and flag changes. Provide either a
contentful.js client through contentful so the panel can fetch preview entries, or pass
pre-fetched entries: { audiences, experiences }.
Preview overrides can force audiences, variants, and inline-variable flag values. Validate a forced
variant by opening the panel, selecting a non-baseline variant, and watching the optimized entry
change without a page reload. Validate an inline flag by forcing a flag value in the panel and
checking that getFlag() or states.flag(name) returns that value while the panel is open. While
the panel is open, optimized entries live-update so authors can inspect changes. Legacy preview
widget globals are not target extension points.
Run these checks after the core runtime migration works:
window.ninetailed plugin global remains.@ninetailed/experience.js-plugin, window.ninetailed.plugins,
window.ninetailed.consent, and __nt-consent__.| Symptom | Check |
|---|---|
| Blocked events disappear | Observe states.blockedEventStream or onEventBlocked; blocked events are diagnostics, not a replay queue. |
| Vendor events duplicate | Dedupe forwarded accepted events by messageId outside component or subscriber lifecycles. |
| Preview attaches but does not update entries | Attach to the live Web SDK and confirm the panel has audience and experience entries. |
| Consent appears accepted in the app but SDK blocks events | Confirm the app passes the current consent decision into the target SDK runtime and that allowedEventTypes matches policy. |