Showing posts with label Sitecore AI. Show all posts
Showing posts with label Sitecore AI. Show all posts

Wednesday, 17 June 2026

Two CMSs, One Website: Managing Routing During WordPress to Sitecore Migration

June 17, 2026 0

 


Introduction

Migrating an enterprise website from WordPress to Sitecore is not a one-time event.

Most organizations have hundreds of pages, multiple business stakeholders, SEO considerations, and ongoing content publishing requirements. A complete cutover often introduces unnecessary risk, especially when business teams expect uninterrupted service throughout the migration journey.

In one of our recent migration projects, the business decided to move from WordPress to Sitecore AI using a phased rollout strategy rather than a full migration in one shot. The objective was simple: migrate content incrementally while ensuring visitors continued to experience a single website.

Although the concept sounds straightforward, the routing architecture required careful planning.

During the migration period:

  • Some pages were served from Sitecore.
  • Some pages remained in WordPress.
  • Both platforms had to coexist.
  • Existing URLs could not change.
  • SEO rankings had to be protected.
  • Content teams needed the flexibility to migrate sections independently.

The challenge was not migrating content. The challenge was making two CMS platforms behave like one website.

This article explains the architecture, routing strategy, and Netlify Edge Function implementation we used to achieve that goal.

The Migration Challenge

The original website was fully managed in WordPress. The target platform was Sitecore AI running on a modern composable architecture. 

Migrating every page at once was not realistic. Different business units owned different sections of the website. Some content areas were ready for migration while others required redesign, content review, or approval cycles.

As a result, both platforms needed to remain active for several months. The business had one non-negotiable requirement:

Users must continue accessing content through the same URLs regardless of which CMS serves the page.

For example:

/products/business-banking

/resources/industry-report

/about-us

/contact

Those URLs already had search engine rankings, backlinks, marketing campaign references, and bookmarks.

Changing them was not an option.

High-Level Architecture

The website was hosted on Netlify, which provided an ideal place to introduce a routing layer.

The architecture looked like this:



Every request entered through Netlify. The Edge Function acted as a traffic controller. Instead of maintaining a large routing table, the architecture relied on Sitecore being the primary source of truth. If Sitecore could resolve a route, the request remained in Sitecore. If Sitecore could not resolve the route, the request automatically fell back to WordPress. This approach simplified migration management considerably.

Why We Chose a 404 Fallback Model

One of the first design decisions involved determining how route ownership would be managed.

Several approaches were considered:

Central Route Registry

Maintain a database containing all migrated routes. While technically possible, it introduced additional maintenance overhead. Every migration release would require route updates. Every rollback would require route updates. Operational complexity grows quickly.

Migration Mapping File

Store route ownership inside configuration files. This works for smaller websites but becomes difficult to maintain as the number of migrated pages increases.

Sitecore-First Routing

Allow Sitecore to handle every request first. If Sitecore returns content, serve it. If Sitecore returns 404, fall back to WordPress. This was the simplest and most maintainable option.

The implementation follows exactly this pattern. The Edge Function calls the Sitecore application first through context.next(). If Sitecore returns anything other than a 404, the response is immediately returned to the visitor. Only when Sitecore responds with a 404 does the WordPress proxy logic execute.

export default async function handler(req: Request, context: Context) {
  const requestUrl = new URL(req.url);
  const wpBase = new URL(WORDPRESS_BASE_URL);
  const proxyReq = req.clone();

  const sitecoreResponse = await context.next();
  if (sitecoreResponse.status !== 404) return sitecoreResponse;

  try {
    const normalizedPath = normalizeWordPressPath(requestUrl.pathname);
    const wpUrl = new URL(
      `${normalizedPath}${requestUrl.search}`,
      wpBase.origin
    ).toString();

    const proxyHeaders = buildProxyHeaders(proxyReq, wpBase);
    const wordpressResponse = await fetchWordPressWithRedirects(
      wpUrl,
      proxyReq,
      proxyHeaders
    );

    const responseHeaders = rewriteLocationHeader(
      wordpressResponse.headers,
      requestUrl,
      wpBase
    );

    return new Response(wordpressResponse.body, {
      status: wordpressResponse.status,
      headers: responseHeaders,
    });
  } catch (error) {
    console.error("[router] WordPress proxy error:", error);
    return sitecoreResponse;
  }
}

GitHub Link- router.ts

Request Flow

The request lifecycle is straightforward.



This design creates a natural migration path. The moment a page is published in Sitecore, Sitecore becomes the owner of that URL. No routing table updates are required. No deployment changes are required. The ownership transition happens automatically.

URL Normalization Challenges

One challenge we encountered involved differences between Sitecore and WordPress URL structures.

During development and content migration, requests sometimes included:

/staging/5474/about-us

or

/old-site/en/banking

These routes made sense in Sitecore but did not exist in WordPress.

To handle this, the Edge Function performs URL normalization before forwarding requests to WordPress.

The router removes:

  • Staging prefixes
  • Sitecore site identifiers
  • Locale prefixes

Examples:

/staging/5474/about-us

becomes

/about-us/

and

/old-site/en/banking

becomes

/banking/

The router also automatically adds trailing slashes to WordPress page URLs while avoiding modifications to static assets and files. This ensures WordPress receives URLs in the format it expects.

function normalizeWordPressPath(pathname: string): string {
  let path = pathname || "/";

  // Remove staging prefix: /staging/5474/...
  path = path.replace(/^\/staging\/\d+(?=\/|$)/i, "") || "/";

  // Remove Sitecore site+locale prefix: /lng-consultancy/en/banking -> /banking
  path = path.replace(/^\/old-site\/[a-z]{2}(?=\/|$)/i, "") || "/";

  // Optional locale-only fallback: /en/banking -> /banking
  path = path.replace(/^\/[a-z]{2}(?=\/|$)/i, "") || "/";

  if (!path.startsWith("/")) path = `/${path}`;
  if (path === "") path = "/";

  // Add trailing slash for WP page permalinks (not files)
  const looksLikeFile = /\.[a-zA-Z0-9]+$/.test(path);
  if (!looksLikeFile && path !== "/" && !path.endsWith("/")) {
    path = `${path}/`;
  }

  return path;
}

GitHub Link- router.ts

Proxying Requests to WordPress

Once a route is determined to be unavailable in Sitecore, the request is forwarded to WordPress.

The Edge Function constructs a WordPress URL using the normalized path and original query string.

For example:

https://www.company.com/resources/report?id=123

might become:

https://wordpress-site.com/resources/report/?id=123

The visitor never sees this internal URL. Everything continues to appear under the primary website domain. From a user perspective, nothing changes.

Header Management

Forwarding requests sounds simple until authentication, language selection, and browser context enter the picture.

The router selectively forwards important request headers including:

  • Accept
  • Accept-Language
  • User-Agent
  • Content-Type
  • Authorization

At the same time, cookies are intentionally excluded. This was an important decision. Forwarding all cookies from Sitecore requests into WordPress often creates unnecessary coupling between systems and can introduce unexpected behaviour. The router only forwards the information WordPress genuinely needs to generate the response.

function buildProxyHeaders(req: Request, wpBase: URL): Headers {
  const headers = new Headers();

  const passThroughHeaders = [
    "accept",
    "accept-language",
    "user-agent",
    "content-type",
    "authorization",
    // intentionally not forwarding cookie
  ];

  for (const h of passThroughHeaders) {
    const v = req.headers.get(h);
    if (v) headers.set(h, v);
  }

  headers.set("x-forwarded-proto", "https");
  headers.set("x-forwarded-host", wpBase.host);
  headers.set("x-forwarded-server", wpBase.host);

  return headers;
}

GitHub Link- router.ts

Handling Redirects Correctly

Redirects become particularly interesting when multiple systems are involved.

Imagine WordPress returns:

Location:

https://old-site.com/about-us/

Without additional handling, visitors could suddenly be redirected to the WordPress origin. That would expose implementation details and break the unified website experience. To prevent this, the Edge Function rewrites redirect locations before returning responses. Internally generated WordPress redirects are transformed so they continue pointing to the public website domain. Visitors remain on the same website while WordPress remains hidden behind the routing layer.

function rewriteLocationHeader(
  responseHeaders: Headers,
  requestUrl: URL,
  wpBase: URL
): Headers {
  const headers = new Headers(responseHeaders);
  const location = headers.get("location");
  if (!location) return headers;

  try {
    const locUrl = new URL(location, wpBase.origin);
    if (locUrl.host === wpBase.host) {
      headers.set(
        "location",
        `${requestUrl.origin}${locUrl.pathname}${locUrl.search}${locUrl.hash}`
      );
    }
  } catch {
    // ignore invalid location header
  }

  return headers;
}

GitHub Link- router.ts

Managing Redirect Chains

WordPress plugins, SEO tools, and legacy URL rules often generate multiple redirects. The router therefore follows redirects manually. Instead of blindly accepting redirect responses, the implementation performs controlled redirect handling with a maximum redirect threshold. This prevents infinite loops while ensuring legitimate redirects continue to function. Operationally, this proved valuable because migration projects frequently expose old redirect rules that nobody remembers creating. The logging built into the Edge Function helped identify several redirect chains during testing that would otherwise have gone unnoticed.

async function fetchWordPressWithRedirects(
  initialUrl: string,
  req: Request,
  proxyHeaders: Headers
): Promise<Response> {
  const method = req.method.toUpperCase();
  const isGetOrHead = method === "GET" || method === "HEAD";

  if (!isGetOrHead) {
    // Body must be read once from cloned request
    const requestBody = await req.arrayBuffer();
    return fetch(initialUrl, {
      method,
      headers: proxyHeaders,
      body: requestBody,
      redirect: "manual",
    });
  }

  let currentUrl = initialUrl;

  for (let i = 0; i < MAX_REDIRECTS; i++) {
    const res = await fetch(currentUrl, {
      method,
      headers: proxyHeaders,
      redirect: "manual",
    });

    const location = res.headers.get("location");
    const isRedirect = res.status >= 300 && res.status < 400 && !!location;

    console.log(
      `[router] WP fetch ${i + 1}: ${currentUrl} -> status=${res.status}${
        location ? ` location=${location}` : ""
      }`
    );

    if (!isRedirect || !location) return res;
    currentUrl = new URL(location, currentUrl).toString();
  }

  return fetch(currentUrl, {
    method,
    headers: proxyHeaders,
    redirect: "manual",
  });
}

GitHub Link- router.ts

What This Means for Content Teams

One of the biggest advantages of this architecture is that migration ownership shifts from technical teams to content teams.

A typical migration process looks like this:

Before Migration

/about-us

exists only in WordPress. WordPress serves the page.

During Migration

Content authors rebuild the page in Sitecore. The page is tested and approved.

After Publication

Sitecore now resolves:

/about-us

The Edge Function receives a successful Sitecore response. The WordPress fallback is never triggered. Traffic automatically moves to Sitecore. No routing updates are required. No deployment is required. The URL remains unchanged.

Operational Lessons Learned

A few observations became clear during implementation. 

First, simplicity wins.It is tempting to create sophisticated route ownership databases and synchronization processes. In practice, allowing Sitecore to become the route authority dramatically reduced operational overhead.

Second, URL normalization requires more attention than most teams expect. Site structures, locale handling, and legacy URL patterns often contain years of accumulated complexity.

Third, logging is critical.

When a page unexpectedly appears from WordPress instead of Sitecore, the first question is always:

"Why did the fallback happen?"

Detailed routing logs significantly reduce troubleshooting time.

Finally, treat redirects as a first-class migration concern. Redirect behaviour that worked perfectly in a standalone WordPress environment may behave differently once a proxy layer is introduced.

Testing redirect scenarios early saves a lot of production support effort later.

Final Thoughts 

Running two CMS platforms behind a single website sounds complicated, but the routing strategy does not need to be. By placing Netlify Edge Functions in front of both systems and adopting a Sitecore-first, WordPress-fallback approach, we created a migration model that was easy to operate, easy to scale, and easy for content teams to understand.

  • Pages could move from WordPress to Sitecore independently.
  • URLs remained unchanged.
  • SEO value was preserved.
  • Users continued to interact with a single website.

Most importantly, the migration could progress at the pace the business needed without introducing unnecessary technical complexity.

Sometimes the best migration architecture is not the one with the most moving parts. It is the one that quietly stays out of the way and lets the business migrate content with confidence.

GitHub Link- router.ts

References


Tuesday, 21 April 2026

Sitecore AI + Netlify: A Real Issue with Geo Personalization

April 21, 2026 0

 


Problem Statement

We recently faced an issue while working on a Sitecore AI implementation hosted on Netlify.

Our setup was simple. We had deployed the frontend application on Netlify and enabled Sitecore AI embedded personalization. As part of the personalization strategy, we created different page variants based on the user’s country. The expectation was users from different countries should see personalized content to their location.

However, things did not work as expected.

No matter where the user was accessing the site from, the same version of the page was being shown. The personalization rules were not getting applied correctly. At first, it looked like a configuration issue in Sitecore AI, but after checking the rules and setup multiple times, everything seemed fine.


Root Cause Analysis

After digging deeper, we found the real problem.

Sitecore AI was not receiving the actual user’s country information. Instead, it was always picking up the country of the Netlify hosting server. In our case, the site was hosted in the UAE, so every request appeared as if it was coming from the UAE.

Because of this, even if a user accessed the site from Saudi Arabia (or any other country), Sitecore AI still treated them as a UAE user. As a result, the country-based personalization never triggered correctly.

In short, the personalization logic was working, but the input data (user location) was wrong. And because of that, the entire experience broke.


Solution

After understanding the problem, we focused on how Netlify was handling request headers.

We noticed that Netlify always sets the x-forwarded-for header using its edge network IP. Because of this, our logic was always picking that value and skipping any further checks. This caused a bigger issue — Sitecore was reading different edge node IPs on every request. As a result, the detected location kept changing, and users were getting different personalized variants on every page refresh.

To fix this, we changed our approach.

Instead of relying on x-forwarded-for, we decided to always use x-nf-client-connection-ip when it is available. This header gives the actual client IP. This small change ensured that the correct user location is passed every time.

Along with this, we added a middleware in our Next.js application.

We extended the existing PersonalizeMiddleware provided by Sitecore and It overrides one method — getExperienceParams — which is responsible for building the data object sent to Sitecore to decide which personalized variant to show.

class GeoPersonalizeMiddleware extends PersonalizeMiddleware {
  protected getExperienceParams(req: NextRequest) {
    const params = super.getExperienceParams(req);
    const country = req.headers.get('x-country');
    if (country) {
      return { ...params, geo: { country } };
    }
    return params;
  }
}

super.getExperienceParams(req) — first calls the original Sitecore method to get the default params (referrer, UTM, etc.)

req.headers.get('x-country') — reads a header called x-country which Netlify automatically injects on every request with the visitor's detected country code (e.g. "AE", "SA")

If the x-country header exists, it adds a geo: { country } field into the params before sending to Sitecore

This made a big difference. Now Sitecore gets the correct country information on the very first request itself. Because of this, the geo-based personalization rules start working immediately, even before any cookies or user profile data are created.

We also handled one more important case.

Netlify sometimes sends requests from its own prerender system. These are not real users, but background requests used for caching and performance. Netlify marks these requests using a header called netlify-agent-category.

function isNetlifyPrerender(req: NextRequest): boolean {
  const agentCategory = req.headers.get('netlify-agent-category') || '';
  return agentCategory.includes('tooling') || agentCategory.includes('prerender');
}

We added a simple check to detect such requests. If the request is coming from Netlify’s prerender system, we prevent caching for that response. This avoids serving incorrect or cached personalized content to real users.

if (isNetlifyPrerender(req)) {
    response.headers.set('x-middleware-cache', 'no-cache');
    response.headers.set('netlify-cdn-cache-control', 'no-store');
  }

x-middleware-cache: no-cache — tells Next.js middleware layer not to cache this response

In short, the fix had three key parts:

  1. Use the correct client IP instead of the edge IP
  2. Pass the user’s country explicitly to SitecoreAI
  3. Avoid caching issues caused by prerender requests

After applying these changes, the personalization started working correctly for users across different countries.


Tuesday, 31 March 2026

How to Set Up Single Sign-On (SSO) in SitecoreAI (XM Cloud)

March 31, 2026 0

 



In this blog, I'll explain how you can set up Single Sign-On (SSO) in Sitecore AI (XM Cloud). SSO simplifies login management, allowing teams to access the Sitecore Cloud Portal and its applications using their existing identity providers. Sitecore Cloud Portal supports identity providers that use either OpenID Connect (OIDC) or Security Assertion Markup Language (SAML) protocol.

We had a requirement to implement SSO using Microsoft Entra ID. Here I'll explain the step-by-step process to implement that.

Prerequisites

Before starting the configuration, please ensure you have the following access:

  • Azure AD Permissions: The ability to register Sitecore Cloud Portal as an application in Azure AD.
  • Sitecore Cloud Portal Administrative Access: You must hold an Organization Admin or Organization Owner role in Sitecore Cloud Portal.
  • Domain Configuration Access: Permission to create a TXT record with your domain host provider.

Set Up Azure Entra ID

  1. Log in to the Azure Portal.



  2. Go to Microsoft Entra ID → Manage → App registrations.



  3. Click on the New Registration button.
  4. Provide the necessary details:
    • Name – A unique name for your application.
    • Supported account types – Choose based on your requirement:
      • Single tenant only – Use this if your application is meant for users within your organization only.
      • Multi Entra ID tenant – Choose this to allow users from other organizations (e.g., partners) to log in using their credentials.
      • Any Entra ID Tenant + Personal Microsoft accounts – Select this to support both organizational users and personal Microsoft accounts.
      • Personal accounts only – Choose this if the application is intended solely for individual users with personal Microsoft accounts.
    • Redirect URI – Under Redirect URI, select Web and enter https://auth.sitecorecloud.io/login/callback in the URL text box. The redirect URI is the endpoint to which the user is sent by the authorization server after completing its interaction, and to which an access token or authorization code is sent upon successful authorization.




  5. Copy the Application (Client) ID from the newly created app page — you will need it when creating the SSO connection in Sitecore XM Cloud.



  6. Go to the Authentication tab → Settings and check the ID tokens checkbox.



Configure SSO in Sitecore Cloud Portal

  1. Log in to Sitecore Cloud Portal.
  2. Navigate to the SSO Settings:
    • Click on Admin from the top menu.
    • Click Single Sign-On (SSO) from the left navigation, then click Add SSO connection.
    • In the drop-down menu, select OpenID Connect.



  3. In the Add SSO connection dialog, fill in the required details:
    • Email Domain: Enter the email domain(s) associated with this SSO connection (e.g., lng-consultancy.com). You can add up to 50 email domains for a single connection. Only team members with email addresses matching the domains specified here will be able to log in via SSO. Make sure the domains you add are valid and owned by your organization.
    • Connection Type: Choose either Front Channel or Back Channel based on your identity provider's documentation.
    • Discovery URL: Enter the discovery document URL for your Azure Entra ID tenant. Use the Tenant ID copied during the Azure setup. For example: https://login.microsoftonline.com/{yourTenantID}/v2.0/.well-known/openid-configuration
    • Scopes: Include openid, profile, and email. Optionally, add scopes for claims like name, given_name, family_name, and nickname.
    • Client ID: Use the Client ID copied during the Azure Entra ID setup.
    • Client Secret: If using Back Channel (Authorization Code flow), enter the client secret generated in Azure Entra ID.
    • Callback URL: This is the redirect URI provided during app registration (https://auth.sitecorecloud.io/login/callback).



  4. Verifying Your Domain : After saving, a TXT record will be generated. Copy the TXT record and add it to your domain's DNS records. Without domain verification, users will not be able to log in using SSO.
    Example: If your organization owns lng-consultancy.com and lngconsultancy.co.in, you can add both domains in the Email Domain field to allow employees with either domain to log in using their Azure AD credentials.



Enabling the SSO Connection

After verifying the domain and optionally testing your SSO connection, you can enable it.

  1. Navigate to the Sitecore Cloud Portal SSO page.
  2. Locate the SSO connection you want to enable and click Enable.
  3. Once enabled, team members with email addresses matching the SSO connection domain can log in using their identity provider.
I hope this helps you set up SSO in the Sitecore Cloud Portal (XM Cloud). Feel free to drop a comment if you have any questions!

References

Saturday, 14 February 2026

Composable DXP Architecture with Sitecore SaaS: An Architect’s Perspective

February 14, 2026 0

 


Sitecore’s SaaS products — Sitecore AI with XM Cloud, Content Hub, CDP, Personalize, Sitecore Search, and Sitecore Connect — gives architects all the building blocks for a modern composable DXP. The challenge is not what to buy, but how to place each capability without overlap, duplication, or architectural drift.

This post breaks down where each Sitecore SaaS product fits, where it explicitly does not, and the most common misconceptions that derail composable implementations.

The Core Principle of Composable DXP

Composable architecture is based on clearly separating responsibilities:

  • Content Authoring intelligence resides in upstream systems and is decoupled from runtime delivery.
  • The experience delivery layer is intentionally lightweight, stateless, and deterministic, focused purely on rendering and orchestration.
  • Decisioning, personalization, experimentation, and optimization are executed within dedicated engines (e.g., CDP, Personalization) rather than embedded in the presentation tier.
  • Integration follows an event-driven architecture (EDA) pattern using APIs, webhooks, and message streams instead of tightly coupled, point-to-point integrations.

Sitecore SaaS

Sitecore AI with XM Cloud: Content Backbone, Authoring Intelligence

Sitecore AI improves the content creation and authoring layer in a composable DXP.It helps content teams to generate, improve, tagging, and organize content.

Its main role is to provide intelligence during the content creation process. It is not to handle real-time personalization or decision-making when users are visiting the website.

Where Sitecore AI Fits:

  • Structured content authoring and governance
  • Headless-first content delivery
  • Workflow, approvals, and publishing
  • Multi-channel content reuse
  • AI-assisted content drafting and summarization
  • SEO and content quality recommendations
  • Metadata, tagging, and semantic enrichment
  • Content consistency and discoverability

Where Sitecore AI Does Not Fit:

  • Real-time personalization
  • Audience targeting
  • Decision orchestration
  • Behavioral analysis
If SitecoreAI is making runtime decisions in your architecture, something has gone wrong.

Sitecore CDP: The Customer Information

Sitecore CDP is the system where we store customer data and behavior. It helps to understand the customer, based on everything we know?

Where CDP Fits

  • Identity resolution and profile unification
  • Event ingestion from all touchpoints
  • Audience segmentation
  • Historical and real-time behavioral insights

Where CDP Does Not Fit

  • Content creation or management
  • UI-level personalization rendering
  • Frontend experience orchestration

CDP informs decisions — it does not render experiences.

Sitecore Personalize: The Decisioning Engine


Sitecore Personalize is a real-time personalization and experimentation engine. It uses customer behavioral data from CDP to deliver tailored content, offers, and experiences to each user. It also supports A/B testing and optimization to continuously improve engagement and conversion.

It decides what should this user see right now?

Where Personalize Fits

Real-time decisioning
Offer and experience selection
A/B and multivariate testing
Context-aware personalization
Personalize answers a different question:

Where Personalize Does Not Fit

  • Content authoring
  • Long-term data storage
  • Analytics reporting beyond experiments
Personalize depends on CDP context and XM Cloud content, it does not replace either.

Sitecore Search: The Discovery Engine

Sitecore Search sits in the delivery layer and focuses on intelligent content and product discovery. It consumes structured content from XM Cloud and behavioral signals (where available) to improve search relevance and recommendations. However, it complements but not replaces CDP or Personalize for customer data management and real-time decisioning.

Where Sitecore Search Fits

  • AI-driven search relevance
  • Semantic search and ranking
  • Faceting and filtering
  • Query personalization (based on context signals)
  • Content and product indexing

Where Sitecore Search Does Not Fit

  • Full customer profile management
  • Cross-channel journey orchestration
  • Experience-level decisioning beyond search results

Search answers a specific runtime question: Given this query and context, what content should rank first?
Search optimizes discovery, not the entire experience.

Content Hub: The Content Operations Engine


Sitecore Content Hub is a centralized content and Assets operations platform that manages content across its full lifecycle, from planning and creation to approval and distribution. It combines DAM, content management, and marketing resource management to ensure governance, collaboration, and structured content delivery across channels.
Content Hub belongs in the content operations layer, upstream of XM Cloud

Where Content Hub Fits

  • Digital Asset Management (DAM)
  • Product Content Management (PCM)
  • Content Planning & Marketing Resource Management (MRM)
  • Workflow, collaboration, and brand governance
  • Centralized asset distribution across channels

Where Content Hub Does Not Fit

  • Runtime experience delivery
  • Real-time personalization
  • Frontend rendering
  • Customer profile management

Content Hub answers an operational question:
How do we create, manage, approve, and distribute content at enterprise scale?

Sitecore Connect: The Integration Layer

Sitecore Connect is an integration layer that connects Sitecore products with external systems like CRM, ERP, and marketing platforms. It enables low-code, event-driven integrations and automated workflows without building custom point-to-point connections, supporting a scalable composable architecture. Connect ensures your composable stack stays loosely coupled.

Where Connect Fits

  • SaaS-to-SaaS integrations
  • Trigger-based workflows
  • Event propagation between Sitecore products and external systems
  • Decoupled integration patterns

Where Connect Does Not Fit

  • Core business logic execution
  • High-frequency synchronous runtime calls
  • Replacing enterprise integration platforms

Use Connect for orchestration — not as a runtime dependency.

Putting It Together: Reference Responsibility Map

Capability

Sitecore AI

CDP

Personalize

Search

Content Hub

Connect

Content authoring

✅

❌

❌

❌

✅

❌

Digital asset management

❌

❌

❌

❌

✅

❌

Content delivery

✅

❌

❌

❌

❌

❌

Customer profiles

❌

✅

❌

❌

❌

❌

Real-time decisioning

❌

❌

✅

❌

❌

❌

Experiments & testing

❌

❌

✅

❌

❌

❌

AI content enrichment

✅

❌

❌

❌

❌

❌

Intelligent search & ranking

❌

❌

❌

✅

❌

❌

Event-based integration

❌

❌

❌

❌

❌

✅

 

Wrong vs Right Architecture: A Reality Check for Architects

❌ The Wrong Architecture 

In many so-called composable DXP setups, everything is pushed into XM Cloud.

Typical mistakes:

  • Personalization rules built directly inside CMS components
  • Frontend calling multiple systems synchronously at runtime
  • AI treated as a real-time decision engine
  • Direct point-to-point integrations between products

What this looks like:

  • XM Cloud deciding who sees what
  • Sitecore AI used for runtime personalization
  • Frontend full of conditional logic
  • CDP used only as a data storage system

What happens because of this:

  • Personalization issues are hard to debug
  • Runtime performance becomes slow and unstable
  • Scaling to new channels requires major rewrites
  • Architects become bottlenecks

This type of setup may work in a demo. It does not survive real traffic or real business growth.

✅ The Right Architecture (Truly Composable)

In a proper composable setup, each product has a clear and strict responsibility.

  • XM Cloud handles content authoring and publishing
  • Sitecore AI improves content before publishing
  • CDP manages customer identity and behavior data
  • Personalize handles real-time decisioning
  • The frontend stays lightweight and predictable
  • Connect manages integrations using asynchronous, event-driven flows

What this gives you:

  • Stable and predictable performance
  • Independent scaling of each system
  • Faster experimentation and testing
  • Clear ownership between teams

This approach is cleaner, safer, and built to scale.

Architect’s Rule of Thumb

If personalization logic lives inside your CMS, you don’t have a composable DXP — you have a monolith exposed through APIs.

Common Misconceptions That Break Composable DXPs

XM Cloud Can Handle Personalization

XM Cloud can render personalized content. It should not decide personalization rules.
Decisioning belongs to Personalize.

Sitecore AI Replaces CDP or Personalize

Sitecore AI helps content authors. CDP and Personalize help end users.
They solve different problems in different layers.

We Can Add CDP and Personalize Later

Skipping optimization in the initial design leads to:

  • Tight frontend coupling
  • Rework during scaling
  • Inconsistent personalization logic

Composable architecture must be designed for future growth from the start.

Point-to-Point Integrations Are Faster

Yes — initially.

But without Connect or event-driven integration:

  • SaaS sprawl increases
  • Ownership becomes unclear
  • Changes become risky

Final Architect’s Take

Composable DXP with Sitecore SaaS works only when responsibilities are clearly defined:

  • Content Hub manages content operations and assets
  • XM Cloud handles content delivery
  • Sitecore AI supports authoring intelligence
  • Sitecore Search manages discovery
  • CDP manages customer data
  • Personalize makes decisions
  • Connect handles integrations

When each product does only what it is designed to do, composable architecture becomes simple and scalable.

Design with clarity.
Scale with confidence.