Skip to content

Migrating from Optimizely

The recommended path is the overlay: SeeAMess follows a live Optimizely site, editors move over page by page, and adopt ends the relation. This page covers what is the same either way: how data maps, what happens to your code, and how the result is checked.

  1. Identity is the Optimizely GUID. A content’s GUID becomes its ID, a content type’s GUID becomes the type ID. Nothing is re-keyed, so links survive.
  2. Integer IDs are kept on the side. The compatibility API answers with them, so front-ends and integrations that hold integer IDs keep working.
  3. Nothing is dropped. A value the importer cannot interpret becomes an opaque value holding the source type name and the raw stored value.
  4. Read from SQL. The adapter reads Optimizely’s database directly and read-only: it is fast, needs no code on the source site, and sees every version.
  5. Both systems can run at once. Migration is a period, not a moment.
Optimizely SeeAMess
Language branches Locales. Language-neutral content (the system folders) is served for every locale.
Content types and property definitions Manifest types and fields, in the source’s schema scope. Field ID = UUIDv5(type ID, property name), the same rule as the .NET SDK.
Content Content, parents first. PeerOrder becomes the sort index, deleted content is soft-deleted.
Work content (every version, every language, every status) Versions. Re-runs are idempotent.
Access rights Access lists, mask copied as is. The default acl policy uses Optimizely’s bit meanings.
Site and host definitions Sites and hosts
Blobs Media, addressed by hash
Users and roles Not imported: users move to your identity provider. User names are kept as strings.

Property values: strings become text; XhtmlString becomes richText with HTML kept byte for byte; content areas become JSON arrays of items, keeping every attribute; content and page references become reference; booleans, numbers and dates keep their type. Anything else, and list properties, becomes opaque.

Version statuses: published → published (or superseded when another version is live), previously published → superseded, delayed publish → scheduled, checked in → ready, rejected → rejected. The original status code is kept with each version.

  • Content models port by changing base types and attributes: PageData → Page, [CultureSpecific] → [Localized], XhtmlString → RichText, ContentReference → ContentRef, and removing virtual. Because field IDs come from the type GUID and property name, a ported class matches imported data with no mapping file. See Define content types.
  • Headless front-ends change one base URL. The compatibility API returns the Content Delivery API v3 shape. Moving to the native Delivery API is independent of the content migration and can happen any time later.
  • Event handlers and scheduled jobs become extension-host event handlers, interceptors and jobs. They are rewritten, not converted. See Extending SeeAMess.
  • Razor rendering is not supported. SeeAMess is headless.

A migration is accepted on evidence, not on a clean log:

  1. Counts. Contents, versions per status and locales match between the source and SeeAMess.
  2. Delivery parity. seeamess-migrate verify compares, for every published URL in every locale, the JSON from Optimizely’s Content Delivery API and from the compatibility API, field by field. Expected differences are listed in the tool; anything else is a failure.
  3. Opaque report. seeamess-migrate assess lists every value that will be carried without being understood, by type and count.

Measured against a live Optimizely CMS 12: 12 responses compared, no unexpected differences. The one documented difference is that Optimizely shows its global assets folder under a UI display string (“For All Sites”).

For a one-time move without an overlay period, import syncs into a source and adopts the content in the same transaction:

seeamess-migrate import --source "<connection string>" --url http://127.0.0.1:5080 --token dev

Running it again overwrites the imported contents, including edits made in SeeAMess since.

Exporting back into Optimizely is designed but not built. Until it is, the supported rollback is the overlay’s phases 1 and 2, where Optimizely remains the system of record and nothing needs to be written back.