Kentico to Optimizely Migration: A Technical Guide
Technical guide to migrating content from Kentico (KX13) to Optimizely CMS. Covers SQL extraction, content model mapping, widget-to-block transformation, and Content Management API import.
Planning a migration?
Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.
Schedule a free call- 1,500+ migrations completed
- Zero downtime guaranteed
- Transparent, fixed pricing
- Project success responsibility
- Post-migration support included
Kentico to Optimizely Migration: A Technical Guide
TL;DR: Migrating from Kentico to Optimizely requires translating a database-driven, three-table-join content model into strictly typed C# classes (PaaS) or API-registered types (SaaS). No automated converter exists. Content types must be rebuilt before data can be ingested via Optimizely's Content Management API. The hardest engineering challenge is parsing Kentico's page builder widget JSON and mapping it into Optimizely's block-based ContentArea properties.
Moving from Kentico (Xperience 13 or earlier) to Optimizely (formerly Episerver) is a transition between two fundamentally different .NET architectures. Both run on Microsoft stacks, but their approaches to content modeling, data storage, and component rendering share almost no common ground — and no automated converter bridges the gap.
Teams typically initiate this migration for two reasons: they are facing the December 31, 2026 Kentico Xperience 13 end-of-support deadline and have opted for Optimizely's enterprise DXP capabilities over upgrading to Xperience by Kentico, or they are consolidating multiple legacy CMS instances into a single Optimizely environment.
This guide covers the full technical path: extraction from Kentico, content model mapping, field type translation, import into Optimizely, and the edge cases that break generic migration plans.
Two separate clocks. The data migration — extracting from Kentico and importing into Optimizely — is one workstream. The broader replatform project (redesigning templates, rebuilding integrations, training editors, QA) is a separate effort measured in months. This guide focuses on the data migration. Don't conflate the two when planning timelines.
How Kentico and Optimizely content models differ
You cannot migrate content until the target schema exists, and how that schema is created dictates the entire migration strategy.
Kentico is database-driven. Content types (Page Types) are created in the admin UI. Each page type generates a dedicated SQL table (e.g., CONTENT_Article) joined with system tables CMS_Tree (tree position and node-level properties shared across language versions) and CMS_Document (per-language metadata, versioning, page builder widget data). Relationships, categories, and attachments each live in their own tables (CMS_Relationship, CMS_DocumentCategory, CMS_Attachment).
Optimizely is code-first (PaaS) or API-registered (SaaS). In Optimizely CMS 12 (PaaS), content types are defined entirely in C# using classes that inherit from PageData, BlockData, or MediaData. The database schema is abstracted via Entity Framework. In CMS 13 and SaaS, Optimizely moves toward a Graph-first architecture where content types are registered via the Content Definitions API and delivered through Optimizely Graph (GraphQL). If a content type does not exist in the Optimizely solution, the API rejects any attempt to create content of that type with a 400 Bad Request and an error body identifying the unknown type.
| Concept | Kentico (KX13) | Optimizely (CMS 12/13) |
|---|---|---|
| Page storage | CMS_Tree + CMS_Document + coupled table |
PageData class → SQL or SaaS content store |
| Reusable components | Widgets (Page Builder JSON) | BlockData / Sections / Elements (CMS 13) |
| Media | CMS_Attachment (DB) or Media Library (filesystem/Azure Blob) |
MediaData in content repository or DAM |
| Custom fields | Coupled table columns per page type | Properties on content type classes |
| Taxonomy | Categories (CMS_Category) + Tags |
Content properties or custom taxonomy types |
| Relationships | CMS_Relationship table |
Content references (ContentReference, ContentArea) |
| URL structure | NodeAliasPath + URL patterns |
Routing via content tree or custom routing |
| Multilingual | Per-language rows in CMS_Document + coupled tables |
Per-language versions of each content item |
The fundamental mismatch: Kentico separates tree structure from content across a three-table join, while Optimizely collapses everything into a single typed object. Extraction queries must join across multiple Kentico tables, and the import must flatten that result into Optimizely's property model.
Because of this, a Kentico to Optimizely migration is strictly a two-phase project:
- The Rebuild: The development team writes content type classes in Optimizely (C# for PaaS, or API definitions for SaaS) that correspond to the legacy Kentico page types and blocks.
- The Data Migration: Content is extracted from Kentico, transformed to match the new Optimizely models, and pushed via the Content Management API.
Field type mapping: Kentico → Optimizely
This is the most common lookup gap engineers encounter. Kentico's field types, as defined in CMS_Class.ClassFormDefinition XML, must be mapped to the appropriate Optimizely property types before any import code is written.
| Kentico Field Type | Optimizely Property Type | Notes |
|---|---|---|
Text (short string) |
string |
Direct mapping |
LongText (plain) |
string |
Direct mapping |
LongText with HTML encoding |
XhtmlString |
Must use XhtmlString, not string; Optimizely's rich text editor requires this type to resolve internal links |
Integer |
int |
Direct mapping |
LongInteger |
long |
Direct mapping |
Double |
double |
Direct mapping |
Decimal |
decimal |
Direct mapping |
DateTime |
DateTime |
Direct mapping; normalize timezone offsets |
Boolean |
bool |
Direct mapping |
File / FileAttachment |
ContentReference |
Create a MediaData object first; store the returned Content ID as ContentReference |
DocRelationships |
ContentArea |
Each related document becomes a ContentReference within a ContentArea |
GUID |
string or custom property |
No native GUID property type in Optimizely; store as string or use a custom attribute |
Binary |
Upload via /api/episerver/v3.0/media |
Extract binary, upload separately, reference by Content ID |
Category tree (CMS_Category) |
Custom taxonomy property or ContentReference list |
No native category tree; design a taxonomy content type or use tags |
Critical: Any LongText field in Kentico that stores HTML — including fields edited via Kentico's WYSIWYG editor — must become XhtmlString in Optimizely, not string. If you declare the property as string, Optimizely will store the value but the CMS editor will not recognize it as rich text, and internal link resolution will not function. Verify field encoding by checking the ClassFormDefinition XML in CMS_Class for each field's resolvedefaultculture and htmlencode attributes.
How to extract data from Kentico
Direct SQL extraction is the most reliable path for pulling content out of Kentico when the target is a non-Kentico platform. While Kentico offers a REST API, it does not reliably paginate the content tree (CMS.DocumentEngine.TreeNode). Attempting to pull a 50,000-page site through the REST API routinely results in timeouts or incomplete datasets. The Site Export Wizard produces a proprietary ZIP package designed for Kentico-to-Kentico transfers and is not useful for cross-platform migrations.
For a detailed breakdown of every extraction method and their limits, see our guide on how to export data from Kentico.
SQL extraction pattern
Kentico provides View_CMS_Tree_Joined, a convenience view that joins the most common columns from CMS_Tree and CMS_Document. For the actual content fields, join in the coupled data table for each page type:
SELECT
v.NodeAliasPath,
v.DocumentName,
v.DocumentCulture,
v.DocumentUrlPath,
v.NodeGUID,
v.DocumentModifiedWhen,
v.DocumentPageBuilderWidgets,
n.NewsTitle,
n.NewsSummary,
n.NewsText
FROM View_CMS_Tree_Joined v
INNER JOIN CONTENT_News n
ON v.DocumentForeignKeyValue = n.NewsID
WHERE v.ClassName = 'CMS.News'
AND v.DocumentCulture = 'en-us'
AND v.NodeSiteID = 1
ORDER BY v.NodeOrderRepeat this pattern for every page type. Enumerate your page types first by querying CMS_Class where ClassIsDocumentType = 1, then build per-type extraction queries that join the correct coupled table. The coupled table name is stored in CMS_Class.ClassTableName.
What to extract separately
- Media library files: Stored on the filesystem under
~/<sitename>/media/or in Azure Blob Storage. Extract file paths and metadata fromMedia_FileandMedia_Librarytables, then copy the binary files. - Page attachments: Stored as BLOBs in
CMS_Attachment.AttachmentBinary(or on the filesystem ifCMSStorageProviderAssemblyis configured for file system). JoinCMS_AttachmenttoCMS_DocumentviaAttachmentDocumentIDto associate attachments with parent pages. - Relationships: Query
CMS_Relationshipjoined toCMS_RelationshipNamefor relationship type labels. You'll need these to recreate content references in Optimizely. - Categories and tags: Query
CMS_Categoryfor the full category tree andCMS_DocumentCategoryfor page-to-category mappings. - Form data: Each online form has its own table, named after the form code name with a
BizForm_prefix. QueryCMS_Formfor the list of forms, then query each form's data table directly. - Page Builder widget data: Stored in the
DocumentPageBuilderWidgetscolumn — covered in detail below.
Delta sync detection
For incremental syncs after the initial bulk migration — used to capture content created or modified in Kentico while the Optimizely build is in progress — use DocumentModifiedWhen in CMS_Document as the change detection column:
SELECT v.NodeGUID, v.DocumentModifiedWhen, v.DocumentCulture
FROM View_CMS_Tree_Joined v
WHERE v.DocumentModifiedWhen > @LastSyncTimestamp
AND v.NodeSiteID = 1
ORDER BY v.DocumentModifiedWhen ASCStore @LastSyncTimestamp as the completion time of the previous run. For newly created documents, DocumentModifiedWhen is set on creation, so this query captures both creates and updates. For deletions, compare the full set of NodeGUID values from Kentico against the GUIDs stored in your migration mapping table, and delete orphaned Optimizely records. Note that DocumentModifiedWhen reflects the last editorial save, not the last publish — a document can have a recent DocumentModifiedWhen while still in a Draft workflow state.
Mapping Kentico widgets to Optimizely blocks
This is the most complex data transformation in the migration. Both systems use a component-based page builder, but they store data in fundamentally different ways, and no automated mapping exists.
The Kentico widget structure
In Kentico MVC, page builder data is stored in the DocumentPageBuilderWidgets column as a deeply nested JSON string containing editable areas, sections, zones, widgets, and their configured properties:
{
"editableAreas": [
{
"identifier": "mainZone",
"sections": [
{
"identifier": "2a8b9c-section",
"zones": [
{
"identifier": "zone-1",
"widgets": [
{
"typeIdentifier": "Custom.HeroWidget",
"identifier": "f8d7e6",
"properties": {
"Heading": "Welcome to the new site",
"BackgroundImage": "~/getmedia/12345/hero.jpg"
}
}
]
}
]
}
]
}
]
}The Optimizely block structure
Optimizely handles components using Blocks — instances of BlockData that act as independent content objects (IContent). Pages contain a ContentArea property, which holds a list of references to these blocks by ID.
To migrate the Hero Widget above, the migration script must:
- Parse the Kentico JSON and identify
Custom.HeroWidget. - POST to Optimizely's Content Management API to create a new
HeroBlockwith the extracted properties. - Store the returned Optimizely Content ID.
- Append that Content ID to the
ContentAreaarray of the parent page.
The key structural difference: Kentico embeds widget data directly inside the page record as JSON, while Optimizely stores blocks as separate content objects referenced by ID. For widget-heavy pages, you have two options:
- Extract the content within each widget and map it to Optimizely blocks or content areas (preferred, lossless).
- Treat the rendered HTML as the migration source (lossy, but practical for highly complex layouts with no clean data mapping).
What happens when a widget has no registered mapping
If your migration script encounters a typeIdentifier in Kentico's widget JSON that has no corresponding Optimizely block type defined in your mapping configuration, you have three handling strategies:
- Fail loudly: Log the unmapped identifier, skip the widget, and flag the page for manual review. This is the safest option — it prevents silent data loss.
- Emit a raw HTML block: If the Kentico widget renders predictable HTML, you can execute the Kentico rendering layer against the widget properties and store the output in a generic
XhtmlStringblock. This captures the content but loses editability. - Skip silently: Do not do this. Pages that appear complete but are missing components cause QA failures that are difficult to trace back to the migration script.
The Optimizely API will return 400 Bad Request with a message referencing the unknown contentType if you attempt to create a block using an identifier that hasn't been registered. Build a pre-flight check that validates all typeIdentifier values found in the Kentico export against the registered block types in the Optimizely environment before running the full migration.
Importing data via Optimizely's Content Management API
Optimizely offers different import pathways depending on whether you're targeting PaaS or SaaS. The API surfaces differ in base URL and authentication mechanism, but the ETL logic is identical.
Optimizely PaaS (CMS 12/13)
The Content Management API provides REST endpoints for creating, updating, and deleting content objects. Authentication uses OAuth 2.0 with the client credentials flow. In Optimizely CMS 12, configure an OpenID Connect client in the Optimizely admin under /episerver/cms/admin → API Clients. Create a client with client_credentials grant type and assign it the epi:cms:contentmanagement:write scope. Request a bearer token from /api/token and pass it in the Authorization: Bearer <token> header on all subsequent requests.
To create a page, POST to /api/episerver/v3.0/content with the content type name matching the C# class name registered in the Optimizely solution:
{
"name": "Welcome to the new site",
"parentLink": {
"id": 5
},
"contentType": ["Page", "ArticlePage"],
"language": {
"name": "en"
},
"status": "Published",
"properties": {
"ArticleTitle": {
"value": "Welcome to the new site"
},
"ArticleBody": {
"value": "<p>Extracted from Kentico.</p>"
},
"MainContentArea": {
"value": [
{
"contentLink": {
"id": 102
}
}
]
}
}
}Notice MainContentArea: instead of embedding block data directly inside the page payload (as Kentico does with widget JSON), Optimizely stores a contentLink referencing the ID of the block created in a prior API call. This means blocks must always be created before the pages that reference them.
Idempotent upserts via PUT: To make migration reruns safe, supply a contentGuid in your request body derived from the source Kentico NodeGUID. Use PUT to /api/episerver/v3.0/content/{contentGuid} — if the GUID already exists, Optimizely updates the record; if it doesn't, it creates it. Without a supplied GUID, POST always creates a new record, causing duplicates on reruns. The GUID must be included in both the URL and the request body for PUT to behave as an upsert.
Partial failure recovery: The Optimizely Content Management API does not provide transaction semantics across multiple requests. If a block creates successfully (HTTP 201) but the subsequent parent page write fails (HTTP 400 or 500), the block exists as an orphan in the content repository. Maintain a local migration state table — keyed on Kentico NodeGUID — recording the Optimizely Content ID and write status for every object. On rerun, skip objects with a recorded successful status and retry only failures. This prevents orphan accumulation and makes state inspectable.
Optimizely SaaS
For SaaS deployments, the Content API base URL is https://api.cms.optimizely.com/v1/content. Authentication uses OAuth 2.0 client credentials against Optimizely's identity service — credentials are provisioned through the Optimizely CMS SaaS portal. Content types are registered via the Content Definitions API using PUT /api/content/v3/types/{typeId}, which is idempotent and safe to run on every deployment.
Rate limit awareness. Optimizely Graph enforces per-tenant rate limits measured over a 10-second window. Read endpoints allow up to 1,500 requests per 10 seconds (150 QPS average), but write endpoints have lower limits not publicly documented — implement exponential backoff on HTTP 429 responses regardless. Graph pagination caps at 10,000 total results using skip/limit parameters; use cursor-based pagination (after cursor field) for datasets larger than 10,000 records. For write-heavy bulk imports, batch requests where possible and distribute load across time rather than sending at maximum throughput.
The .episerverdata package route
Optimizely supports importing .episerverdata packages through the admin UI (Settings → Import Data). This is an Optimizely-to-Optimizely format — you cannot generate it from Kentico natively. Building a tool to generate these files programmatically from Kentico data requires reverse-engineering the package format, which is an XML manifest wrapping serialized content objects and binary assets. For most Kentico-to-Optimizely migrations, the Content Management API is the cleaner and more maintainable path.
What breaks during content model mapping
Some Kentico content constructs don't have direct Optimizely equivalents. These require design decisions, not just scripting.
Custom modules and custom tables. Kentico custom module classes (CMS_Class with ClassIsCustomTable = 1) have no direct Optimizely equivalent. Options: model them as custom BlockData or PageData content types in Optimizely, move the data to an external relational store and expose it via a headless API, or collapse the data into existing content types where it logically belongs.
Workflow and version history. Kentico's CMS_VersionHistory records prior document versions and workflow state transitions. Neither the version history nor the workflow state machine migrates to Optimizely's versioning system. Standard practice is to migrate only the current published version, optionally the latest draft if it differs materially, and archive or discard historical versions.
E-commerce data. Kentico's built-in e-commerce module (SKU tables, order tables, customer records) is a separate migration from CMS content. Optimizely Customized Commerce has its own product catalog model with distinct APIs. Plan this as an independent workstream.
Kentico macros in rich text. Kentico's macro engine can inject dynamic expressions into stored content: {% raw %}{% CurrentDocument.DocumentName %}{% endraw %}, {%Resource("string.key")%}, URL macros like ~/getdoc/{GUID}/alias.aspx. These will not resolve in Optimizely — they will render as literal strings. Before migrating any LongText field that may contain macros, run a scan across the full extracted dataset for {% patterns. For each macro type, determine whether the resolved value can be pre-computed at migration time (embed the static value), replaced with an Optimizely equivalent, or flagged for manual editorial review. Common macro types in Kentico page content:
| Macro Pattern | Resolution Strategy |
|---|---|
~/getmedia/{GUID}/{filename} |
Look up in Media_File by GUID; replace with Optimizely media URL |
~/getattachment/{GUID}/{filename} |
Look up in CMS_Attachment by GUID; replace with Optimizely media URL |
~/getdoc/{GUID}/{alias} |
Look up NodeGUID in CMS_Tree; replace with Optimizely content URL |
{%CurrentDocument.FieldName%} |
Pre-compute from extraction query; embed static value |
{%Resource("key")%} |
Resolve from CMS_ResourceString; embed static string |
Use an HTML parser (HtmlAgilityPack in .NET, BeautifulSoup in Python) to traverse rich text fields — regex-based replacement fails on nested attributes, encoded characters, and multi-line patterns.
How to handle media and attachments
Media files are the most common source of post-migration broken links. Kentico serves media through URL patterns like /getmedia/{GUID}/{filename} (media library) or /getattachment/{GUID}/{filename} (page attachments). Optimizely uses its own URL patterns for media in the content repository.
Media migration workflow
- Extract binaries from Kentico. If stored on filesystem, copy files from
~/<sitename>/media/. If stored as database BLOBs (CMSStorageProviderAssemblyset to DB mode), extractAttachmentBinaryfromCMS_AttachmentorFileBinaryfromMedia_Fileand write to disk. Pull metadata (FileName,FileExtension,FileMimeType,FileGUID) fromMedia_FileandCMS_Attachment. - Upload to Optimizely. The PaaS API requires a two-step process: POST the binary to
/api/episerver/v3.0/mediawith a multipart form body to receive an upload URI and a provisional Content ID, then PATCH the metadata (name, alt text, folder parent link) to finalize the media object. For SaaS, consult the Asset Management API documentation specific to your tenant configuration. - Build a URL mapping table. Record every legacy Kentico media GUID and its corresponding new Optimizely Content ID and URL. This table is used in the rich text rewriting step.
- Rewrite references in content. After all media is uploaded, scan every migrated rich text field and replace Kentico media URLs with new Optimizely URLs using the mapping table and an HTML parser.
SEO preservation: URLs, redirects, and metadata
Kentico's URL structure is driven by NodeAliasPath and configurable URL patterns per page type. Optimizely generates URLs based on the content tree hierarchy (PaaS) or a configurable routing model (SaaS/headless).
The non-negotiable: build a complete 301 redirect map before cutover. Extract every published URL from Kentico — use DocumentUrlPath if populated, otherwise derive from NodeAliasPath using the URL pattern configured for each page type in CMS_DocumentType — and map it to the corresponding Optimizely URL. Implement redirects at the application level, CDN edge, or WAF. Missing this step means losing accumulated search equity proportional to the age and link authority of the migrated content.
Also migrate per-page:
DocumentPageTitle→ Optimizely's SEO title propertyDocumentPageDescription→ Meta description propertyDocumentPageKeyWords→ Meta keywords (if still used)- Open Graph fields (
DocumentOGTitle,DocumentOGDescription,DocumentOGImage) if custom columns exist - Canonical URL overrides if stored as custom page type fields
Optimizely SaaS vs. PaaS: how the target changes the migration
Optimizely SaaS is fully managed — no customer-deployed code for the CMS itself. Content types are defined via the Content JS SDK or the Content Definitions API (PUT /api/content/v3/types). Import happens through the REST Content API at https://api.cms.optimizely.com/v1/content. SaaS suits teams migrating from Kentico who want to eliminate self-hosted .NET infrastructure.
Optimizely PaaS (CMS 12 or CMS 13 on DXP Cloud) gives you a deployed .NET application. Content types are defined as C# classes decorated with [ContentType] attributes. Import uses the Content Management API at /api/episerver/v3.0/content, custom scheduled jobs, or direct database seeding during initial setup. PaaS provides more control but requires maintaining infrastructure, managing deployments, and handling CMS upgrades.
The migration ETL logic — extract from Kentico, transform to target schema, load via API — is identical between the two. The differences are in authentication setup, API base URLs, content type registration mechanism, and rate limit profiles.
How long does a Kentico to Optimizely data migration take?
The data migration itself — extracting from Kentico and importing into Optimizely — typically completes within 1–5 business days under the following baseline assumptions: standard page content without binary-heavy media, fewer than 50 widget types requiring mapping, media stored on filesystem rather than database BLOBs, and a dedicated API import process running at approximately 50–100 writes per minute (accounting for block-before-page sequencing and rate limit headroom).
Factors that extend this estimate: high widget density per page, media stored as database BLOBs (extraction is significantly slower), large binary file counts requiring upload, and complex rich text with high macro density requiring per-field parsing. By volume:
- 1–500 documents: 1–2 days
- 500–5,000 documents: 3–7 days
- 5,000+ documents: Custom engagement, typically an initial bulk migration followed by delta syncs
These estimates cover data migration only. The broader replatform — designing Optimizely content types, building templates, rebuilding integrations, QA, editor training — is a separate project measured in months. Start the scoping process at least 3–4 months before any hard deadline.
For context on what Kentico's own migration tooling covers for the KX13 → Xperience by Kentico path, see our analysis of what Kentico's Migration Tool doesn't move. Many of the same gaps — Page Builder data, custom modules, version history — apply when the target is Optimizely instead.
When this migration doesn't make sense
- Small marketing sites on KX13 with no need for Optimizely's A/B testing, personalization, or experimentation stack. Optimizely's licensing (reported by third-party trackers at $40K–$150K+ annually; Optimizely does not publish public pricing) may not be recoverable from the value delivered. Evaluate lighter headless alternatives before committing.
- Heavily customized Kentico instances with custom modules, e-commerce, and deep third-party integrations. In these cases, the replatform effort surrounding the CMS migration will substantially exceed the data migration cost. Budget for the full scope before approving the project.
- Teams evaluating Xperience by Kentico as the target instead: Kentico provides its own Migration Tool for KX13 → XbyK transfers, which handles structured content but has documented gaps.
What a ClonePartner-led migration covers
We handle the data extraction, transformation, and API ingestion — not the replatform. A typical engagement:
- Connect accounts — read access to your Kentico database and write access to your Optimizely instance.
- Migration checklist — documented mapping of every content type, field type (using the table above), media path, URL rule, and macro resolution strategy.
- Sample migration — unlimited test runs until every content type maps correctly, included in the fixed project price.
- Full migration — production run, typically over a weekend to minimize disruption to the live site.
- Delta sync — content created or updated in Kentico after the bulk run (detected via
DocumentModifiedWhencomparison) is synced before final cutover.
Validation includes record-count parity checks, field-level spot validation, referential integrity verification (no orphaned ContentArea references), and binary checksum comparison for media files. One fixed price — no hourly billing, no per-record metering.
Frequently Asked Questions
- Can I migrate from Kentico to Optimizely automatically?
- No automated converter exists between Kentico and Optimizely. The content models are structurally different — Kentico uses a three-table join (CMS_Tree, CMS_Document, coupled tables) while Optimizely uses strongly-typed PageData objects. Migration requires custom extraction queries, field-by-field mapping, and programmatic import via Optimizely's Content Management API.
- How do you migrate Kentico page builder widgets to Optimizely?
- Kentico stores widget data as JSON in the DocumentPageBuilderWidgets database column. This JSON must be parsed, mapped to Optimizely BlockData objects, created via the Optimizely Content Management API as separate content items, and then injected as content link references into a parent page's ContentArea property.
- How long does a Kentico to Optimizely data migration take?
- The data migration itself typically completes within 1–5 business days, depending on data volume, content complexity, and API rate limits. Small datasets under 10,000 records can finish in under 24 hours. This is separate from the broader replatform project (templates, integrations, QA), which is measured in months.
- What Kentico data doesn't migrate cleanly to Optimizely?
- Page Builder widget JSON, version history, workflow state, custom modules, and custom table data have no direct Optimizely equivalents. E-commerce data (SKUs, orders) requires a separate migration to Optimizely Customized Commerce. Widget content must be extracted and remapped to Optimizely blocks.
- Should I target Optimizely SaaS or PaaS for a Kentico migration?
- SaaS is fully managed with content types defined via the Content Definitions API — good if you want to avoid maintaining another .NET deployment. PaaS (CMS 12/13 on DXP Cloud) gives you a deployed .NET app with C#-defined content types and more import flexibility. The extraction and transformation logic is the same for both targets.