diff --git a/CHANGELOG.md b/CHANGELOG.md
index 41f34247b6..3d7d589379 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -38,6 +38,11 @@ Our versioning strategy is as follows:
 ### 🛠 Breaking Changes
 
 * `[create-sitecore-jss]` The `nextjs-personalize` initializer add-on template has been removed and is replaced by the `nextjs-xmcloud` initializer template. You can use the interactive prompts or the `--xmcloud` argument to include this template. ([#1653](https://github.com/Sitecore/jss/pull/1653))
+* `[templates/nextjs]` `[sitecore-jss-nextjs]` CloudSDK Integration ([#1652](https://github.com/Sitecore/jss/pull/1652)):
+  * Removed the following properties from _PersonalizeMiddleware_: _getPointOfSale_, _clientKey_, _endpoint_. You now need to provide _sitecoreEdgeContextId_ as a replacement.
+  * _PersonalizeMiddleware_ has transitioned to utilizing the _CloudSDK_ package, replacing the previous dependency on _Engage_.
+  * Introduced _Context_ class, that is used to initialize the application Context and shared Software Development Kits (SDKs). Accessible within the _@sitecore-jss/sitecore-jss-nextjs/context_ submodule.
+  * Point of Sale resolution is fully removed, now it's handled by Sitecore Edge Proxy
 
 ## 21.5.0
 
diff --git a/packages/create-sitecore-jss/src/templates/nextjs-sxa/src/pages/_app.tsx b/packages/create-sitecore-jss/src/templates/nextjs-sxa/src/pages/_app.tsx
index 7bbf99b96c..b4ab44a12f 100644
--- a/packages/create-sitecore-jss/src/templates/nextjs-sxa/src/pages/_app.tsx
+++ b/packages/create-sitecore-jss/src/templates/nextjs-sxa/src/pages/_app.tsx
@@ -1,6 +1,7 @@
 import type { AppProps } from 'next/app';
 import { I18nProvider } from 'next-localization';
 import { SitecorePageProps } from 'lib/page-props';
+import Bootstrap from 'src/Bootstrap';
 
 import 'assets/main.scss';
 
@@ -8,12 +9,17 @@ function App({ Component, pageProps }: AppProps<SitecorePageProps>): JSX.Element
   const { dictionary, ...rest } = pageProps;
 
   return (
-    // Use the next-localization (w/ rosetta) library to provide our translation dictionary to the app.
-    // Note Next.js does not (currently) provide anything for translation, only i18n routing.
-    // If your app is not multilingual, next-localization and references to it can be removed.
-    <I18nProvider lngDict={dictionary} locale={pageProps.locale}>
-      <Component {...rest} />
-    </I18nProvider>
+    <>
+      <Bootstrap {...pageProps} />
+      {/*
+        // Use the next-localization (w/ rosetta) library to provide our translation dictionary to the app.
+        // Note Next.js does not (currently) provide anything for translation, only i18n routing.
+        // If your app is not multilingual, next-localization and references to it can be removed.
+      */}
+      <I18nProvider lngDict={dictionary} locale={pageProps.locale}>
+        <Component {...rest} />
+      </I18nProvider>
+    </>
   );
 }
 
diff --git a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/.env b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/.env
index 45ccca7ccc..5292cf2bef 100644
--- a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/.env
+++ b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/.env
@@ -7,21 +7,11 @@ SITECORE_EDGE_CONTEXT_ID=
 
 # ==============================================
 
-# Your Sitecore CDP API target (specific to your data center region)
-NEXT_PUBLIC_CDP_TARGET_URL=
-
-# Your Sitecore CDP client key
-NEXT_PUBLIC_CDP_CLIENT_KEY=
-
 # An optional Sitecore Personalize scope identifier.
 # This can be used to isolate personalization data when multiple XM Cloud Environments share a Personalize tenant.
 # This should match the PAGES_PERSONALIZE_SCOPE environment variable for your connected XM Cloud Environment.
 NEXT_PUBLIC_PERSONALIZE_SCOPE=
 
-# Your Sitecore CDP point(s) of sale
-# Can be provided as a single value (mypoint.com) or a multi-value JSON with locales ({"en":"en.mypoint.com","fr":"fr.mypoint.com"} etc)
-NEXT_PUBLIC_CDP_POINTOFSALE=
-
 # Timeout (ms) for Sitecore CDP requests to respond within. Default is 400.
 PERSONALIZE_MIDDLEWARE_CDP_TIMEOUT=
 
diff --git a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/package.json b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/package.json
index 33d06644d2..4394f65580 100644
--- a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/package.json
+++ b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/package.json
@@ -1,7 +1,7 @@
 {
   "dependencies": {
-    "@sitecore/components": "~1.0.19",
-    "@sitecore/engage": "^1.4.1",
+    "@sitecore/components": "^1.1.0",
+    "@sitecore-cloudsdk/events": "^0.1.1",
     "@sitecore-feaas/clientside": "^0.4.12"
   }
 }
diff --git a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/scripts/config/plugins/edge-platform.ts b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/scripts/config/plugins/edge-platform.ts
index d8779ff0bb..9680df17ca 100644
--- a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/scripts/config/plugins/edge-platform.ts
+++ b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/scripts/config/plugins/edge-platform.ts
@@ -11,7 +11,9 @@ class EdgePlatformPlugin implements ConfigPlugin {
   order = 2;
 
   async exec(config: JssConfig) {
-    const sitecoreEdgeUrl = process.env[`${constantCase('sitecoreEdgeUrl')}`] || 'https://edge-platform.sitecorecloud.io';
+    const sitecoreEdgeUrl =
+      process.env[`${constantCase('sitecoreEdgeUrl')}`]?.replace(/\/$/, '') ||
+      'https://edge-platform.sitecorecloud.io';
     const sitecoreEdgeContextId = process.env[`${constantCase('sitecoreEdgeContextId')}`];
 
     if (config.sitecoreApiKey && sitecoreEdgeContextId) {
diff --git a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/Bootstrap.tsx b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/Bootstrap.tsx
new file mode 100644
index 0000000000..a8f082c8bb
--- /dev/null
+++ b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/Bootstrap.tsx
@@ -0,0 +1,24 @@
+import { SitecorePageProps } from 'lib/page-props';
+import { context } from 'src/lib/context';
+import { siteResolver } from 'lib/site-resolver';
+import config from 'temp/config';
+
+/**
+ * The Bootstrap component is the entry point for performing any initialization logic
+ * that needs to happen early in the application's lifecycle.
+ */
+const Bootstrap = (props: SitecorePageProps): JSX.Element | null => {
+  const site = props.layoutData?.sitecore.context.site;
+  const siteInfo = siteResolver.getByName(site?.name || config.siteName);
+
+  /**
+   * Initializes the application Context and associated Software Development Kits (SDKs).
+   * This function is the entry point for setting up the application's context and any SDKs that are required for its proper functioning.
+   * It prepares the resources needed to interact with various services and features within the application.
+   */
+  context.init({ siteName: siteInfo.name });
+
+  return null;
+};
+
+export default Bootstrap;
diff --git a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/byoc/index.ts b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/byoc/index.ts
index aeb744d961..3e9486da3f 100644
--- a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/byoc/index.ts
+++ b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/byoc/index.ts
@@ -1,6 +1,6 @@
 import * as FEAAS from '@sitecore-feaas/clientside/react';
 import dynamic from 'next/dynamic';
-import config from 'temp/config';
+import { context } from 'lib/context';
 /**
  * This is an out-of-box bundler for External components (BYOC) (see Sitecore documentation for more details)
  * It enables registering components in client-only or SSR/hybrid contexts
@@ -8,10 +8,7 @@ import config from 'temp/config';
  */
 
 // Set context properties to be available within BYOC components
-FEAAS.setContextProperties({
-  sitecoreEdgeUrl: config.sitecoreEdgeUrl,
-  sitecoreEdgeContextId: config.sitecoreEdgeContextId,
-});
+FEAAS.setContextProperties(context);
 
 // Import your client-only components via client-bundle. Nextjs's dynamic() call will ensure they are only rendered client-side
 const ClientBundle = dynamic(() => import('./index.client'), {
diff --git a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/components/CdpPageView.tsx b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/components/CdpPageView.tsx
index 190c0af1d7..d0d6d53f49 100644
--- a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/components/CdpPageView.tsx
+++ b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/components/CdpPageView.tsx
@@ -1,54 +1,23 @@
 import {
   CdpHelper,
   LayoutServicePageState,
-  SiteInfo,
   useSitecoreContext,
-  PosResolver,
 } from '@sitecore-jss/sitecore-jss-nextjs';
 import { useEffect } from 'react';
 import config from 'temp/config';
-import { init } from '@sitecore/engage';
-import { siteResolver } from 'lib/site-resolver';
+import { context } from 'lib/context';
 
 /**
  * This is the CDP page view component.
- * It uses the Sitecore Engage SDK to enable page view events on the client-side.
+ * It uses the Sitecore Cloud SDK to enable page view events on the client-side.
  * See Sitecore Engage SDK documentation for details.
- * https://www.npmjs.com/package/@sitecore/engage
+ * https://www.npmjs.com/package/@sitecore-cloudsdk/events
  */
 const CdpPageView = (): JSX.Element => {
   const {
     sitecoreContext: { pageState, route, variantId, site },
   } = useSitecoreContext();
 
-  /**
-   * Creates a page view event using the Sitecore Engage SDK.
-   */
-  const createPageView = async (
-    page: string,
-    language: string,
-    site: SiteInfo,
-    pageVariantId: string
-  ) => {
-    const pointOfSale = PosResolver.resolve(site, language);
-    const engage = await init({
-      clientKey: process.env.NEXT_PUBLIC_CDP_CLIENT_KEY || '',
-      targetURL: process.env.NEXT_PUBLIC_CDP_TARGET_URL || '',
-      // Replace with the top level cookie domain of the website that is being integrated e.g ".example.com" and not "www.example.com"
-      cookieDomain: window.location.hostname.replace(/^www\./, ''),
-      // Cookie may be created in personalize middleware (server), but if not we should create it here
-      forceServerCookieMode: false,
-    });
-    engage.pageView({
-      channel: 'WEB',
-      currency: 'USD',
-      pointOfSale,
-      page,
-      pageVariantId,
-      language,
-    });
-  };
-
   /**
    * Determines if the page view events should be turned off.
    * IMPORTANT: You should implement based on your cookie consent management solution of choice.
@@ -68,7 +37,6 @@ const CdpPageView = (): JSX.Element => {
       return;
     }
 
-    const siteInfo = siteResolver.getByName(site?.name || config.siteName);
     const language = route.itemLanguage || config.defaultLanguage;
     const scope = process.env.NEXT_PUBLIC_PERSONALIZE_SCOPE;
 
@@ -78,7 +46,16 @@ const CdpPageView = (): JSX.Element => {
       variantId as string,
       scope
     );
-    createPageView(route.name, language, siteInfo, pageVariantId);
+
+    context.getSDK('Events')?.then((Events) =>
+      Events.pageView({
+        channel: 'WEB',
+        currency: 'USD',
+        page: route.name,
+        pageVariantId,
+        language,
+      })
+    );
   }, [pageState, route, variantId, site]);
 
   return <></>;
diff --git a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/lib/context/index.ts b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/lib/context/index.ts
new file mode 100644
index 0000000000..8ba26ce19f
--- /dev/null
+++ b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/lib/context/index.ts
@@ -0,0 +1,22 @@
+import { Context } from '@sitecore-jss/sitecore-jss-nextjs/context';
+import config from 'temp/config';
+
+import Events from './sdk/events';
+
+/**
+ * List of SDKs to be initialized.
+ * Each SDK is defined as a module with the @type {SDK} type.
+ */
+const sdks = {
+  Events,
+};
+
+/**
+ * Context instance that is used to initialize the application Context and associated Software Development Kits (SDKs).
+ */
+export const context = new Context<typeof sdks>({
+  sitecoreEdgeUrl: config.sitecoreEdgeUrl,
+  sitecoreEdgeContextId: config.sitecoreEdgeContextId,
+  siteName: config.siteName,
+  sdks,
+});
diff --git a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/lib/context/sdk/events.ts b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/lib/context/sdk/events.ts
new file mode 100644
index 0000000000..59d8e7629b
--- /dev/null
+++ b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/lib/context/sdk/events.ts
@@ -0,0 +1,22 @@
+import * as Events from '@sitecore-cloudsdk/events/browser';
+import { SDK } from '@sitecore-jss/sitecore-jss-nextjs/context';
+
+const sdkModule: SDK<typeof Events> = {
+  sdk: Events,
+  init: async (props) => {
+    // Events module can't be initialized on the server side
+    // We also don't want to initialize it in development mode
+    if (typeof window === 'undefined' || process.env.NODE_ENV === 'development') return;
+
+    await Events.init({
+      siteName: props.siteName,
+      sitecoreEdgeContextId: props.sitecoreEdgeContextId,
+      // Replace with the top level cookie domain of the website that is being integrated e.g ".example.com" and not "www.example.com"
+      cookieDomain: window.location.hostname.replace(/^www\./, ''),
+      // Cookie may be created in personalize middleware (server), but if not we should create it here
+      enableBrowserCookie: true,
+    });
+  },
+};
+
+export default sdkModule;
diff --git a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/lib/middleware/plugins/personalize.ts b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/lib/middleware/plugins/personalize.ts
index 44387365a1..6580931843 100644
--- a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/lib/middleware/plugins/personalize.ts
+++ b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/lib/middleware/plugins/personalize.ts
@@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from 'next/server';
 import { PersonalizeMiddleware } from '@sitecore-jss/sitecore-jss-nextjs/middleware';
 import { MiddlewarePlugin } from '..';
 import clientFactory from 'lib/graphql-client-factory';
+import config from 'temp/config';
 import { siteResolver } from 'lib/site-resolver';
 
 /**
@@ -33,8 +34,8 @@ class PersonalizePlugin implements MiddlewarePlugin {
       },
       // Configuration for your Sitecore CDP endpoint
       cdpConfig: {
-        endpoint: process.env.NEXT_PUBLIC_CDP_TARGET_URL || '',
-        clientKey: process.env.NEXT_PUBLIC_CDP_CLIENT_KEY || '',
+        sitecoreEdgeUrl: config.sitecoreEdgeUrl,
+        sitecoreEdgeContextId: config.sitecoreEdgeContextId,
         timeout:
           (process.env.PERSONALIZE_MIDDLEWARE_CDP_TIMEOUT &&
             parseInt(process.env.PERSONALIZE_MIDDLEWARE_CDP_TIMEOUT)) ||
@@ -50,9 +51,6 @@ class PersonalizePlugin implements MiddlewarePlugin {
       excludeRoute: () => false,
       // Site resolver implementation
       siteResolver,
-      // Personalize middleware will use PosResolver.resolve(site, language) (same as CdpPageView) by default to get point of sale.
-      // You can also pass a custom point of sale resolver into middleware to override it like so:
-      // getPointOfSale: (site, language) => { ... }
     });
   }
 
diff --git a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/lib/site-resolver/plugins/default.ts b/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/lib/site-resolver/plugins/default.ts
deleted file mode 100644
index 5244f8e268..0000000000
--- a/packages/create-sitecore-jss/src/templates/nextjs-xmcloud/src/lib/site-resolver/plugins/default.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { SiteInfo } from '@sitecore-jss/sitecore-jss-nextjs/site';
-import { tryParseEnvValue } from '@sitecore-jss/sitecore-jss-nextjs/utils';
-import config from 'temp/config';
-import { SiteResolverPlugin } from '..';
-
-// Resolving from env variable, but it can be expanded or change in future if needed.
-const pointOfSale = tryParseEnvValue<Record<string, string>>(
-  process.env.NEXT_PUBLIC_CDP_POINTOFSALE,
-  { [config.defaultLanguage]: process.env.NEXT_PUBLIC_CDP_POINTOFSALE || '' }
-);
-
-class DefaultPlugin implements SiteResolverPlugin {
-  exec(sites: SiteInfo[]): SiteInfo[] {
-    // Add default/configured site
-    sites.unshift({
-      name: config.siteName,
-      language: config.defaultLanguage,
-      hostName: '*',
-      pointOfSale,
-    });
-
-    return sites;
-  }
-}
-
-export const defaultPlugin = new DefaultPlugin();
diff --git a/packages/create-sitecore-jss/src/templates/nextjs/src/Bootstrap.tsx b/packages/create-sitecore-jss/src/templates/nextjs/src/Bootstrap.tsx
new file mode 100644
index 0000000000..1bb368b21c
--- /dev/null
+++ b/packages/create-sitecore-jss/src/templates/nextjs/src/Bootstrap.tsx
@@ -0,0 +1,12 @@
+/* eslint-disable  @typescript-eslint/no-unused-vars */
+import { SitecorePageProps } from 'lib/page-props';
+
+/**
+ * The Bootstrap component is the entry point for performing any initialization logic
+ * that needs to happen early in the application's lifecycle.
+ */
+const Bootstrap = (_props: SitecorePageProps): JSX.Element | null => {
+  return null;
+};
+
+export default Bootstrap;
diff --git a/packages/create-sitecore-jss/src/templates/nextjs/src/pages/_app.tsx b/packages/create-sitecore-jss/src/templates/nextjs/src/pages/_app.tsx
index 7fef8a5794..37f4f24162 100644
--- a/packages/create-sitecore-jss/src/templates/nextjs/src/pages/_app.tsx
+++ b/packages/create-sitecore-jss/src/templates/nextjs/src/pages/_app.tsx
@@ -1,6 +1,7 @@
 import type { AppProps } from 'next/app';
 import { I18nProvider } from 'next-localization';
 import { SitecorePageProps } from 'lib/page-props';
+import Bootstrap from 'src/Bootstrap';
 
 import 'assets/app.css';
 
@@ -8,12 +9,17 @@ function App({ Component, pageProps }: AppProps<SitecorePageProps>): JSX.Element
   const { dictionary, ...rest } = pageProps;
 
   return (
-    // Use the next-localization (w/ rosetta) library to provide our translation dictionary to the app.
-    // Note Next.js does not (currently) provide anything for translation, only i18n routing.
-    // If your app is not multilingual, next-localization and references to it can be removed.
-    <I18nProvider lngDict={dictionary} locale={pageProps.locale}>
-      <Component {...rest} />
-    </I18nProvider>
+    <>
+      <Bootstrap {...pageProps} />
+      {/*
+        // Use the next-localization (w/ rosetta) library to provide our translation dictionary to the app.
+        // Note Next.js does not (currently) provide anything for translation, only i18n routing.
+        // If your app is not multilingual, next-localization and references to it can be removed.
+      */}
+      <I18nProvider lngDict={dictionary} locale={pageProps.locale}>
+        <Component {...rest} />
+      </I18nProvider>
+    </>
   );
 }
 
diff --git a/packages/sitecore-jss-nextjs/context.d.ts b/packages/sitecore-jss-nextjs/context.d.ts
new file mode 100644
index 0000000000..72e501678d
--- /dev/null
+++ b/packages/sitecore-jss-nextjs/context.d.ts
@@ -0,0 +1 @@
+export * from './types/context/index';
diff --git a/packages/sitecore-jss-nextjs/context.js b/packages/sitecore-jss-nextjs/context.js
new file mode 100644
index 0000000000..e9529d5720
--- /dev/null
+++ b/packages/sitecore-jss-nextjs/context.js
@@ -0,0 +1 @@
+module.exports = require('./dist/cjs/context/index');
diff --git a/packages/sitecore-jss-nextjs/package.json b/packages/sitecore-jss-nextjs/package.json
index dd8d120519..305940d5b5 100644
--- a/packages/sitecore-jss-nextjs/package.json
+++ b/packages/sitecore-jss-nextjs/package.json
@@ -11,7 +11,7 @@
     "test": "mocha --require ./test/setup.js \"./src/**/*.test.ts\" \"./src/**/*.test.tsx\" --exit",
     "prepublishOnly": "npm run build",
     "coverage": "nyc npm test",
-    "generate-docs": "npx typedoc --plugin typedoc-plugin-markdown --readme none --out ../../ref-docs/sitecore-jss-nextjs --entryPoints src/index.ts --entryPoints src/monitoring/index.ts --entryPoints src/editing/index.ts --entryPoints src/middleware/index.ts --githubPages false"
+    "generate-docs": "npx typedoc --plugin typedoc-plugin-markdown --readme none --out ../../ref-docs/sitecore-jss-nextjs --entryPoints src/index.ts --entryPoints src/monitoring/index.ts --entryPoints src/editing/index.ts --entryPoints src/middleware/index.ts --entryPoints src/context/index.ts --entryPoints src/utils/index.ts --entryPoints src/site/index.ts --entryPoints src/graphql/index.ts --githubPages false"
   },
   "engines": {
     "node": ">=12",
@@ -30,7 +30,7 @@
     "url": "https://github.com/sitecore/jss/issues"
   },
   "devDependencies": {
-    "@sitecore/engage": "^1.4.1",
+    "@sitecore-cloudsdk/personalize": "^0.1.1",
     "@types/chai": "^4.3.4",
     "@types/chai-as-promised": "^7.1.5",
     "@types/chai-string": "^1.4.2",
@@ -66,7 +66,8 @@
     "typescript": "~4.9.4"
   },
   "peerDependencies": {
-    "@sitecore/engage": "^1.4.1",
+    "@sitecore-cloudsdk/events": "^0.1.1",
+    "@sitecore-cloudsdk/personalize": "^0.1.1",
     "next": "^13.4.16",
     "react": "^18.2.0",
     "react-dom": "^18.2.0"
diff --git a/packages/sitecore-jss-nextjs/src/context/context.test.ts b/packages/sitecore-jss-nextjs/src/context/context.test.ts
new file mode 100644
index 0000000000..8d7f528500
--- /dev/null
+++ b/packages/sitecore-jss-nextjs/src/context/context.test.ts
@@ -0,0 +1,163 @@
+/* eslint-disable no-unused-expressions */
+/* eslint-disable dot-notation */
+import sinon from 'sinon';
+import { expect } from 'chai';
+import { Context } from './';
+
+describe('Context', () => {
+  const sdks = {
+    Foo: {
+      sdk: { foo: true },
+      init: () =>
+        new Promise<void>((resolve) => {
+          setTimeout(() => {
+            resolve();
+          }, 300);
+        }),
+    },
+    Bar: {
+      sdk: { bar: true },
+      init: () => {
+        return new Promise<void>((resolve) => {
+          setTimeout(() => {
+            resolve();
+          }, 500);
+        });
+      },
+    },
+  };
+
+  const fooInitSpy = sinon.spy(sdks.Foo, 'init');
+  const barInitSpy = sinon.spy(sdks.Bar, 'init');
+
+  const props = {
+    sitecoreEdgeUrl: 'https://edgeurl',
+    sitecoreEdgeContextId: 'contextid',
+    siteName: '',
+    sdks,
+  };
+
+  afterEach(() => {
+    fooInitSpy.resetHistory();
+    barInitSpy.resetHistory();
+  });
+
+  describe('constructor', () => {
+    it('should create a new context', () => {
+      const context = new Context<typeof sdks>(props);
+
+      expect(context.sitecoreEdgeUrl).to.equal(props.sitecoreEdgeUrl);
+      expect(context.sitecoreEdgeContextId).to.equal(props.sitecoreEdgeContextId);
+      expect(context.siteName).to.equal(props.siteName);
+    });
+  });
+
+  describe('init', () => {
+    it('should initialize the context', (done) => {
+      const context = new Context<typeof sdks>(props);
+
+      context.init();
+
+      expect(context.isInitialized).to.be.true;
+      expect(context.siteName).to.equal(props.siteName);
+
+      expect(context.sdks.Bar).to.equal(undefined);
+      expect(context.sdks.Foo).to.equal(undefined);
+
+      Promise.all([
+        context.getSDK('Foo')?.then((sdk) => {
+          expect(fooInitSpy.calledOnce).to.be.true;
+          expect(sdk).to.deep.equal(sdks.Foo.sdk);
+
+          return;
+        }),
+        context.getSDK('Bar')?.then((sdk) => {
+          expect(barInitSpy.calledOnce).to.be.true;
+          expect(sdk).to.deep.equal(sdks.Bar.sdk);
+
+          return;
+        }),
+      ]).then(() => {
+        expect(context.sdks.Foo).to.deep.equal(sdks.Foo.sdk);
+        expect(context.sdks.Bar).to.deep.equal(sdks.Bar.sdk);
+
+        done();
+      });
+    });
+
+    it('should initialize the context with a different site name', (done) => {
+      const context = new Context<typeof sdks>(props);
+
+      context.init({ siteName: 'website' });
+
+      expect(context.isInitialized).to.be.true;
+      expect(context.siteName).to.equal('website');
+
+      expect(context.sdks.Bar).to.equal(undefined);
+      expect(context.sdks.Foo).to.equal(undefined);
+
+      Promise.all([
+        context.getSDK('Foo')?.then((sdk) => {
+          expect(fooInitSpy.calledOnce).to.be.true;
+          expect(sdk).to.deep.equal(sdks.Foo.sdk);
+
+          return;
+        }),
+        context.getSDK('Bar')?.then((sdk) => {
+          expect(barInitSpy.calledOnce).to.be.true;
+          expect(sdk).to.deep.equal(sdks.Bar.sdk);
+
+          return;
+        }),
+      ]).then(() => {
+        expect(context.sdks.Foo).to.deep.equal(sdks.Foo.sdk);
+        expect(context.sdks.Bar).to.deep.equal(sdks.Bar.sdk);
+
+        done();
+      });
+    });
+
+    it('should not initialize the context if it is already initialized', () => {
+      const context = new Context<typeof sdks>(props);
+
+      context.init({ siteName: 'website-1' });
+
+      expect(context.isInitialized).to.be.true;
+
+      context.init({ siteName: 'website-2' });
+
+      expect(context.siteName).to.equal('website-1');
+    });
+  });
+
+  describe('getSDK', () => {
+    it('should return the SDKs', (done) => {
+      const context = new Context<typeof sdks>(props);
+
+      context.init();
+
+      expect(context.sdks.Bar).to.equal(undefined);
+      expect(context.sdks.Foo).to.equal(undefined);
+
+      Promise.all([
+        context.getSDK('Foo')?.then((sdk) => {
+          expect(fooInitSpy.calledOnce).to.be.true;
+          expect(sdk).to.deep.equal(sdks.Foo.sdk);
+
+          return;
+        }),
+        context.getSDK('Bar')?.then((sdk) => {
+          expect(barInitSpy.calledOnce).to.be.true;
+          expect(sdk).to.deep.equal(sdks.Bar.sdk);
+
+          return;
+        }),
+      ]).then(() => {
+        expect(context.sdks.Foo).to.deep.equal(sdks.Foo.sdk);
+        expect(context.sdks.Bar).to.deep.equal(sdks.Bar.sdk);
+
+        done();
+      });
+    });
+  });
+});
diff --git a/packages/sitecore-jss-nextjs/src/context/context.ts b/packages/sitecore-jss-nextjs/src/context/context.ts
new file mode 100644
index 0000000000..89fc384544
--- /dev/null
+++ b/packages/sitecore-jss-nextjs/src/context/context.ts
@@ -0,0 +1,133 @@
+/**
+ * Software Development Kit (SDK) instance
+ */
+export type SDK<SDKType = unknown> = {
+  /**
+   * The Software Development Kit (SDK) library instance
+   */
+  sdk: SDKType;
+  /**
+   * Initializes the Software Development Kit (SDK)
+   */
+  init: (props: InitSDKProps) => Promise<void>;
+};
+
+/**
+ * Software Development Kits (SDKs) to be initialized
+ */
+type SDKModulesType = Record<string, SDK>;
+
+/**
+ * Properties that are passed to the Context.
+ */
+export interface ContextInitProps {
+  /**
+   * Your Sitecore site name
+   */
+  siteName?: string;
+}
+
+/**
+ * Configuration that is passed to the Context.
+ */
+export interface ContextConfig<SDKModules extends SDKModulesType> {
+  /**
+   * Your Sitecore Edge URL
+   */
+  sitecoreEdgeUrl: string;
+  /**
+   * Your Sitecore Edge Context ID
+   */
+  sitecoreEdgeContextId: string;
+  /**
+   * Your Sitecore site name
+   */
+  siteName: string;
+  /**
+   * Software Development Kits (SDKs) to be initialized
+   */
+  sdks: { [module in keyof SDKModules]: SDKModules[module] };
+}
+
+/**
+ * Properties that are passed to the Software Development Kit (SDK) initialization function.
+ */
+type InitSDKProps = Omit<ContextConfig<SDKModulesType>, 'sdks'>;
+
+/**
+ * Context instance that is used to initialize the application Context and associated Software Development Kits (SDKs).
+ */
+export class Context<SDKModules extends SDKModulesType> {
+  /**
+   * Indicates whether the Context and SDK(s) have been initialized
+   */
+  public isInitialized = false;
+  /**
+   * The Sitecore Edge URL
+   */
+  public readonly sitecoreEdgeUrl: string;
+  /**
+   * The Sitecore Edge Context ID
+   */
+  public readonly sitecoreEdgeContextId: string;
+  /**
+   * The Sitecore site name
+   */
+  public siteName: string;
+  /**
+   * Software Development Kits (SDKs) to be initialized
+   */
+  public readonly sdks: { [module in keyof SDKModules]?: SDKModules[module]['sdk'] } = {};
+  /**
+   * Promises for the SDKs
+   */
+  protected sdkPromises: { [module in keyof SDKModules]?: Promise<SDKModules[module]['sdk']> } = {};
+
+  constructor(protected props: ContextConfig<SDKModules>) {
+    this.sitecoreEdgeUrl = props.sitecoreEdgeUrl;
+    this.sitecoreEdgeContextId = props.sitecoreEdgeContextId;
+    this.siteName = props.siteName;
+  }
+
+  public init(props: ContextInitProps = {}) {
+    // Context and SDKs are initialized only once
+    if (this.isInitialized) return;
+
+    this.isInitialized = true;
+
+    if (props.siteName) {
+      this.siteName = props.siteName;
+    }
+
+    // iterate over the SDKs and initialize them
+    for (const sdkName of Object.keys(this.props.sdks) as (keyof SDKModules)[]) {
+      this.initSDK(sdkName);
+    }
+  }
+
+  /**
+   * Retrieves the Software Development Kit (SDK) instance, ensuring it is initialized before returning
+   *
+   * @param {string} name SDK name
+   * @returns initialized SDK
+   */
+  public getSDK<T extends keyof SDKModules>(name: T): Promise<SDKModules[T]['sdk']> | undefined {
+    return this.sdkPromises[name];
+  }
+
+  /**
+   * Initializes the Software Development Kit (SDK)
+   *
+   * @param {T} name SDK name
+   * @returns {void}
+   */
+  protected initSDK<T extends keyof SDKModules>(name: T): void {
+    this.sdkPromises[name] = new Promise((resolve) => {
+      this.props.sdks[name].init(this).then(() => {
+        this.sdks[name] = this.props.sdks[name].sdk;
+
+        resolve(this.sdks[name]);
+      });
+    });
+  }
+}
diff --git a/packages/sitecore-jss-nextjs/src/context/index.ts b/packages/sitecore-jss-nextjs/src/context/index.ts
new file mode 100644
index 0000000000..b7719c3c1b
--- /dev/null
+++ b/packages/sitecore-jss-nextjs/src/context/index.ts
@@ -0,0 +1 @@
+export { Context, ContextConfig, SDK } from './context';
diff --git a/packages/sitecore-jss-nextjs/src/index.ts b/packages/sitecore-jss-nextjs/src/index.ts
index e8f332c66e..7335fa4782 100644
--- a/packages/sitecore-jss-nextjs/src/index.ts
+++ b/packages/sitecore-jss-nextjs/src/index.ts
@@ -101,7 +101,6 @@ export {
   getPersonalizedRewriteData,
   normalizePersonalizedRewrite,
   CdpHelper,
-  PosResolver,
 } from '@sitecore-jss/sitecore-jss/personalize';
 
 export {
@@ -166,6 +165,8 @@ export { BYOCWrapper };
 
 export { ComponentBuilder, ComponentBuilderConfig } from './ComponentBuilder';
 
+export { Context, ContextConfig, SDK } from './context';
+
 export {
   ComponentFactory,
   Image,
diff --git a/packages/sitecore-jss-nextjs/src/middleware/personalize-middleware.test.ts b/packages/sitecore-jss-nextjs/src/middleware/personalize-middleware.test.ts
index 20a9e6a1b1..7383065f00 100644
--- a/packages/sitecore-jss-nextjs/src/middleware/personalize-middleware.test.ts
+++ b/packages/sitecore-jss-nextjs/src/middleware/personalize-middleware.test.ts
@@ -8,7 +8,6 @@ import nextjs, { NextRequest, NextResponse } from 'next/server';
 import { debug } from '@sitecore-jss/sitecore-jss';
 import { SiteResolver } from '@sitecore-jss/sitecore-jss/site';
 import { PersonalizeMiddleware } from './personalize-middleware';
-import { ExperienceParams } from '@sitecore-jss/sitecore-jss/personalize';
 
 use(sinonChai);
 const expect = chai.use(chaiString).expect;
@@ -33,17 +32,7 @@ describe('PersonalizeMiddleware', () => {
   const variantIds = ['variant-1', 'variant-2'];
   const contentId = `${id}_en_${version}`.toLowerCase();
   const defaultLang = 'en';
-  const pointOfSale = 'cdp-pos';
   const referrer = 'http://localhost:3000';
-  const experienceParams: ExperienceParams = {
-    referrer,
-    utm: {
-      campaign: 'utm_campaign',
-      content: null,
-      medium: null,
-      source: null,
-    },
-  };
   const createRequest = (props: any = {}) => {
     const req = {
       ...props,
@@ -164,8 +153,8 @@ describe('PersonalizeMiddleware', () => {
     } = {}
   ) => {
     const cdpConfig = {
-      clientKey: 'cdp-client-key',
-      endpoint: 'http://cdp-endpoint',
+      sitecoreEdgeContextId: '0000-0000-0000',
+      sitecoreEdgeUrl: 'https://foo.bar',
       ...(props?.cdpConfig || {}),
     };
     const edgeConfig = {
@@ -179,18 +168,12 @@ describe('PersonalizeMiddleware', () => {
         name: siteName,
         language: props.language || '',
         hostName: hostname,
-        pointOfSale: {
-          [props.language || defaultLang]: pointOfSale,
-        },
       }));
 
       getByHost = sinon.stub().callsFake((hostName: string) => ({
         name: siteName,
         language: props.language || '',
         hostName,
-        pointOfSale: {
-          [props.language || defaultLang]: pointOfSale,
-        },
       }));
     }
 
@@ -202,24 +185,13 @@ describe('PersonalizeMiddleware', () => {
       edgeConfig,
     });
 
-    const engageServer = (middleware['initializeEngageServer'] = sinon.stub().returns({
-      handleCookie: async () => {
-        return props.handleCookieStub || Promise.resolve();
-      },
-      event: async () => {
-        return Promise.resolve(null);
-      },
-      personalize: async () => {
-        return Promise.resolve({ variantId: props.variantId });
-      },
-      identity: async () => {
-        return Promise.resolve(null);
-      },
-      pageView: async () => {
-        return Promise.resolve(null);
-      },
-      version: '1.0',
-    }));
+    const initPersonalizeServer = (middleware['initPersonalizeServer'] = sinon.stub());
+
+    const personalize = (middleware['personalize'] = sinon.stub().returns(
+      Promise.resolve({
+        variantId: props.variantId,
+      })
+    ));
 
     const getPersonalizeInfo = (middleware['personalizeService']['getPersonalizeInfo'] =
       props.getPersonalizeInfoStub ||
@@ -238,7 +210,8 @@ describe('PersonalizeMiddleware', () => {
       middleware,
       getPersonalizeInfo,
       siteResolver,
-      engageServer,
+      initPersonalizeServer,
+      personalize,
     };
   };
 
@@ -439,7 +412,12 @@ describe('PersonalizeMiddleware', () => {
     it('no variant identified', async () => {
       const req = createRequest();
       const res = createResponse();
-      const { middleware, getPersonalizeInfo, engageServer } = createMiddleware({
+      const {
+        middleware,
+        getPersonalizeInfo,
+        initPersonalizeServer,
+        personalize,
+      } = createMiddleware({
         variantId: undefined,
       });
       const headers = {};
@@ -452,7 +430,8 @@ describe('PersonalizeMiddleware', () => {
         headers,
       });
       expect(getPersonalizeInfo.calledWith('/styleguide', 'en')).to.be.true;
-      expect(engageServer.called).to.be.true;
+      expect(initPersonalizeServer.called).to.be.true;
+      expect(personalize.called).to.be.true;
       validateDebugLog('skipped (no variant identified)');
       expect(finalRes).to.deep.equal(res);
     });
@@ -460,7 +439,12 @@ describe('PersonalizeMiddleware', () => {
       const req = createRequest();
       const res = createResponse();
       const handleCookieStub = sinon.stub().resolves();
-      const { middleware, getPersonalizeInfo, engageServer } = createMiddleware({
+      const {
+        middleware,
+        getPersonalizeInfo,
+        initPersonalizeServer,
+        personalize,
+      } = createMiddleware({
         variantId: 'invalid-variant',
         handleCookieStub,
       });
@@ -474,7 +458,8 @@ describe('PersonalizeMiddleware', () => {
         headers,
       });
       expect(getPersonalizeInfo.calledWith('/styleguide', 'en')).to.be.true;
-      expect(engageServer.called).to.be.true;
+      expect(initPersonalizeServer.called).to.be.true;
+      expect(personalize.called).to.be.true;
       validateDebugLog('skipped (invalid variant)');
       expect(finalRes).to.deep.equal(res);
     });
@@ -492,7 +477,13 @@ describe('PersonalizeMiddleware', () => {
       });
       const res = createResponse();
       const nextRewriteStub = sinon.stub(nextjs.NextResponse, 'rewrite').returns(res);
-      const { middleware, getPersonalizeInfo, siteResolver, engageServer } = createMiddleware({
+      const {
+        middleware,
+        getPersonalizeInfo,
+        siteResolver,
+        initPersonalizeServer,
+        personalize,
+      } = createMiddleware({
         language,
         variantId: 'variant-2',
         personalizeInfo: {
@@ -511,7 +502,8 @@ describe('PersonalizeMiddleware', () => {
         language: language,
       });
       expect(getPersonalizeInfo.calledWith('/styleguide', 'da-DK')).to.be.true;
-      expect(engageServer.calledOnce).to.be.true;
+      expect(initPersonalizeServer.calledOnce).to.be.true;
+      expect(personalize.calledOnce).to.be.true;
       validateEndMessageDebugLog('personalize middleware end in %dms: %o', {
         rewritePath: '/_variantId_variant-2/styleguide',
         headers: {
@@ -534,7 +526,13 @@ describe('PersonalizeMiddleware', () => {
       });
       const res = createResponse();
       const nextRewriteStub = sinon.stub(nextjs.NextResponse, 'rewrite').returns(res);
-      const { middleware, getPersonalizeInfo, siteResolver, engageServer } = createMiddleware({
+      const {
+        middleware,
+        getPersonalizeInfo,
+        siteResolver,
+        initPersonalizeServer,
+        personalize,
+      } = createMiddleware({
         variantId: 'variant-2',
       });
       const finalRes = await middleware.getHandler()(req, res);
@@ -548,7 +546,8 @@ describe('PersonalizeMiddleware', () => {
         language: 'en',
       });
       expect(getPersonalizeInfo.calledWith('/styleguide', 'en')).to.be.true;
-      expect(engageServer.calledOnce).to.be.true;
+      expect(initPersonalizeServer.calledOnce).to.be.true;
+      expect(personalize.calledOnce).to.be.true;
       validateEndMessageDebugLog('personalize middleware end in %dms: %o', {
         rewritePath: '/_variantId_variant-2/styleguide',
         headers: {
@@ -566,13 +565,20 @@ describe('PersonalizeMiddleware', () => {
       const req = createRequest();
       const res = createResponse();
       const nextRewriteStub = sinon.stub(nextjs.NextResponse, 'rewrite').returns(res);
-      const { middleware, getPersonalizeInfo, siteResolver, engageServer } = createMiddleware({
+      const {
+        middleware,
+        getPersonalizeInfo,
+        siteResolver,
+        initPersonalizeServer,
+        personalize,
+      } = createMiddleware({
         variantId: 'variant-2',
       });
       const finalRes = await middleware.getHandler()(req);
 
       expect(getPersonalizeInfo.calledWith('/styleguide', 'en')).to.be.true;
-      expect(engageServer.calledOnce).to.be.true;
+      expect(initPersonalizeServer.calledOnce).to.be.true;
+      expect(personalize.calledOnce).to.be.true;
       validateDebugLog('personalize middleware start: %o', {
         headers: {
           ...req.headers,
@@ -599,7 +605,13 @@ describe('PersonalizeMiddleware', () => {
       const req = createRequest({ headerValues: { referer: null } });
       const res = createResponse();
       const nextRewriteStub = sinon.stub(nextjs.NextResponse, 'rewrite').returns(res);
-      const { middleware, getPersonalizeInfo, siteResolver, engageServer } = createMiddleware({
+      const {
+        middleware,
+        getPersonalizeInfo,
+        siteResolver,
+        initPersonalizeServer,
+        personalize,
+      } = createMiddleware({
         variantId: 'variant-2',
       });
       const finalRes = await middleware.getHandler()(req, res);
@@ -613,7 +625,8 @@ describe('PersonalizeMiddleware', () => {
         language: 'en',
       });
       expect(getPersonalizeInfo.calledWith('/styleguide', 'en')).to.be.true;
-      expect(engageServer.calledOnce).to.be.true;
+      expect(initPersonalizeServer.calledOnce).to.be.true;
+      expect(personalize.calledOnce).to.be.true;
       validateEndMessageDebugLog('personalize middleware end in %dms: %o', {
         rewritePath: '/_variantId_variant-2/styleguide',
         headers: {
@@ -635,7 +648,13 @@ describe('PersonalizeMiddleware', () => {
         },
       });
       const nextRewriteStub = sinon.stub(nextjs.NextResponse, 'rewrite').returns(res);
-      const { middleware, getPersonalizeInfo, engageServer, siteResolver } = createMiddleware({
+      const {
+        middleware,
+        getPersonalizeInfo,
+        initPersonalizeServer,
+        personalize,
+        siteResolver,
+      } = createMiddleware({
         variantId: 'variant-2',
       });
       const finalRes = await middleware.getHandler()(req, res);
@@ -649,7 +668,8 @@ describe('PersonalizeMiddleware', () => {
         language: 'en',
       });
       expect(getPersonalizeInfo.calledWith('/styleguide', 'en', 'foo')).to.be.true;
-      expect(engageServer.calledOnce).to.be.true;
+      expect(initPersonalizeServer.calledOnce).to.be.true;
+      expect(personalize.calledOnce).to.be.true;
       validateEndMessageDebugLog('personalize middleware end in %dms: %o', {
         rewritePath: '/_variantId_variant-2/styleguide',
         headers: {
@@ -672,7 +692,13 @@ describe('PersonalizeMiddleware', () => {
         },
       });
       const nextRewriteStub = sinon.stub(nextjs.NextResponse, 'rewrite').returns(res);
-      const { middleware, getPersonalizeInfo, engageServer, siteResolver } = createMiddleware({
+      const {
+        middleware,
+        getPersonalizeInfo,
+        initPersonalizeServer,
+        personalize,
+        siteResolver,
+      } = createMiddleware({
         variantId: 'variant-2',
       });
       const finalRes = await middleware.getHandler()(req, res);
@@ -686,7 +712,8 @@ describe('PersonalizeMiddleware', () => {
         language: 'en',
       });
       expect(getPersonalizeInfo.calledWith('/styleguide', 'en', siteName)).to.be.true;
-      expect(engageServer.calledOnce).to.be.true;
+      expect(initPersonalizeServer.calledOnce).to.be.true;
+      expect(personalize.calledOnce).to.be.true;
       validateEndMessageDebugLog('personalize middleware end in %dms: %o', {
         rewritePath: '/_variantId_variant-2/_site_nextjs-app/styleguide',
         headers: {
@@ -708,7 +735,13 @@ describe('PersonalizeMiddleware', () => {
       });
       const res = createResponse();
       const nextRewriteStub = sinon.stub(nextjs.NextResponse, 'rewrite').returns(res);
-      const { middleware, getPersonalizeInfo, engageServer, siteResolver } = createMiddleware({
+      const {
+        middleware,
+        getPersonalizeInfo,
+        initPersonalizeServer,
+        personalize,
+        siteResolver,
+      } = createMiddleware({
         variantId: 'variant-2',
       });
       const finalRes = await middleware.getHandler()(req, res);
@@ -722,7 +755,8 @@ describe('PersonalizeMiddleware', () => {
         language: 'en',
       });
       expect(getPersonalizeInfo.calledWith('/styleguide', 'en', siteName)).to.be.true;
-      expect(engageServer.calledOnce).to.be.true;
+      expect(initPersonalizeServer.calledOnce).to.be.true;
+      expect(personalize.calledOnce).to.be.true;
       validateEndMessageDebugLog('personalize middleware end in %dms: %o', {
         rewritePath: '/_variantId_variant-2/styleguide',
         headers: {
@@ -744,12 +778,19 @@ describe('PersonalizeMiddleware', () => {
       });
       const res = createResponse();
       const nextRewriteStub = sinon.stub(nextjs.NextResponse, 'rewrite').returns(res);
-      const { middleware, getPersonalizeInfo, engageServer, siteResolver } = createMiddleware({
+      const {
+        middleware,
+        getPersonalizeInfo,
+        initPersonalizeServer,
+        personalize,
+        siteResolver,
+      } = createMiddleware({
         variantId: 'variant-2',
         defaultHostname: 'foobar',
       });
       const finalRes = await middleware.getHandler()(req, res);
-      expect(engageServer.calledOnce).to.be.true;
+      expect(initPersonalizeServer.calledOnce).to.be.true;
+      expect(personalize.calledOnce).to.be.true;
       validateDebugLog('personalize middleware start: %o', {
         headers: { ...req.headers },
         hostname: 'foobar',
@@ -796,13 +837,19 @@ describe('PersonalizeMiddleware', () => {
 
       const getPersonalizeInfoWithError = sinon.stub().throws(error);
 
-      const { middleware, getPersonalizeInfo, engageServer } = createMiddleware({
+      const {
+        middleware,
+        getPersonalizeInfo,
+        initPersonalizeServer,
+        personalize,
+      } = createMiddleware({
         getPersonalizeInfoStub: getPersonalizeInfoWithError,
       });
 
       const finalRes = await middleware.getHandler()(req, res);
 
-      expect(engageServer.called).to.be.false;
+      expect(initPersonalizeServer.called).to.be.false;
+      expect(personalize.called).to.be.false;
 
       expect(getPersonalizeInfo.called).to.be.true;
       expect(errorSpy.getCall(0).calledWith('Personalize middleware failed:')).to.be.true;
diff --git a/packages/sitecore-jss-nextjs/src/middleware/personalize-middleware.ts b/packages/sitecore-jss-nextjs/src/middleware/personalize-middleware.ts
index 03601daab8..000f439e32 100644
--- a/packages/sitecore-jss-nextjs/src/middleware/personalize-middleware.ts
+++ b/packages/sitecore-jss-nextjs/src/middleware/personalize-middleware.ts
@@ -3,22 +3,22 @@ import {
   GraphQLPersonalizeService,
   GraphQLPersonalizeServiceConfig,
   getPersonalizedRewrite,
-  PosResolver,
+  PersonalizeInfo,
 } from '@sitecore-jss/sitecore-jss/personalize';
-import { SiteInfo } from '@sitecore-jss/sitecore-jss/site';
 import { debug } from '@sitecore-jss/sitecore-jss';
 import { MiddlewareBase, MiddlewareBaseConfig } from './middleware';
-import { initServer, EngageServer } from '@sitecore/engage';
+import { init, personalize } from '@sitecore-cloudsdk/personalize/server';
 
 export type CdpServiceConfig = {
   /**
-   * Your Sitecore CDP API endpoint
+   * Your Sitecore Edge Platform endpoint
+   * Default is https://edge-platform.sitecorecloud.io
    */
-  endpoint: string;
+  sitecoreEdgeUrl?: string;
   /**
-   * The client key to use for authentication
+   * Your unified Sitecore Edge Context Id
    */
-  clientKey: string;
+  sitecoreEdgeContextId: string;
   /**
    * The Sitecore CDP channel to use for events. Uses 'WEB' by default.
    */
@@ -42,13 +42,6 @@ export type PersonalizeMiddlewareConfig = MiddlewareBaseConfig & {
    * Configuration for your Sitecore CDP endpoint
    */
   cdpConfig: CdpServiceConfig;
-  /**
-   * function to resolve point of sale for a site
-   * @param {Siteinfo} site to get info from
-   * @param {string} language to get info for
-   * @returns point of sale value for site/language combination
-   */
-  getPointOfSale?: (site: SiteInfo, language: string) => string;
 };
 
 /**
@@ -101,22 +94,55 @@ export class PersonalizeMiddleware extends MiddlewareBase {
     };
   }
 
-  protected initializeEngageServer(
-    hostName: string,
-    site: SiteInfo,
-    language: string
-  ): EngageServer {
-    const engageServer = initServer({
-      clientKey: this.config.cdpConfig.clientKey,
-      targetURL: this.config.cdpConfig.endpoint,
-      pointOfSale: this.config.getPointOfSale
-        ? this.config.getPointOfSale(site, language)
-        : PosResolver.resolve(site, language),
-      cookieDomain: hostName,
-      forceServerCookieMode: true,
-    });
+  protected async initPersonalizeServer({
+    hostname,
+    siteName,
+    request,
+    response,
+  }: {
+    hostname: string;
+    siteName: string;
+    request: NextRequest;
+    response: NextResponse;
+  }): Promise<void> {
+    await init(
+      {
+        sitecoreEdgeUrl: this.config.cdpConfig.sitecoreEdgeUrl,
+        sitecoreEdgeContextId: this.config.cdpConfig.sitecoreEdgeContextId,
+        siteName,
+        cookieDomain: hostname,
+        enableServerCookie: true,
+      },
+      request,
+      response
+    );
+  }
 
-    return engageServer;
+  protected async personalize(
+    {
+      params,
+      personalizeInfo,
+      language,
+      timeout,
+    }: {
+      personalizeInfo: PersonalizeInfo;
+      params: ExperienceParams;
+      language: string;
+      timeout?: number;
+    },
+    request: NextRequest
+  ) {
+    const personalizationData = {
+      channel: this.config.cdpConfig.channel || 'WEB',
+      currency: this.config.cdpConfig.currency ?? 'USD',
+      friendlyId: personalizeInfo.contentId,
+      params,
+      language,
+    };
+
+    return (await personalize(personalizationData, request, timeout)) as {
+      variantId: string;
+    };
   }
 
   protected getExperienceParams(req: NextRequest): ExperienceParams {
@@ -194,36 +220,27 @@ export class PersonalizeMiddleware extends MiddlewareBase {
       return response;
     }
 
-    const engageServer = this.initializeEngageServer(hostname, site, language);
+    await this.initPersonalizeServer({
+      hostname,
+      siteName: site.name,
+      request: req,
+      response,
+    });
 
-    // creates the browser ID cookie on the server side
-    // and includes the cookie in the response header
-    try {
-      await engageServer.handleCookie(req, response, timeout);
-    } catch (error) {
-      debug.personalize('skipped (browser id generation failed)');
-      throw error;
-    }
     const params = this.getExperienceParams(req);
 
     debug.personalize('executing experience for %s %s %o', personalizeInfo.contentId, params);
 
-    const personalizationData = {
-      channel: this.config.cdpConfig.channel || 'WEB',
-      currency: this.config.cdpConfig.currency ?? 'USA',
-      friendlyId: personalizeInfo.contentId,
-      params,
-      language,
-    };
-
     let variantId;
 
-    // Execute targeted experience in CDP
+    // Execute targeted experience in Personalize SDK
     // eslint-disable-next-line no-useless-catch
     try {
-      variantId = ((await engageServer.personalize(personalizationData, req, timeout)) as {
-        variantId: string;
-      }).variantId;
+      const personalization = await this.personalize(
+        { personalizeInfo, params, language, timeout },
+        req
+      );
+      variantId = personalization.variantId;
     } catch (error) {
       throw error;
     }
diff --git a/packages/sitecore-jss-nextjs/tsconfig.json b/packages/sitecore-jss-nextjs/tsconfig.json
index 348881666f..9d2cf9eaff 100644
--- a/packages/sitecore-jss-nextjs/tsconfig.json
+++ b/packages/sitecore-jss-nextjs/tsconfig.json
@@ -14,6 +14,7 @@
     "types",
     "typings",
     "dist",
+    "context.d.ts",
     "middleware.d.ts",
     "editing.d.ts",
     "monitoring.d.ts",
diff --git a/packages/sitecore-jss/src/graphql/graphql-edge-proxy.test.ts b/packages/sitecore-jss/src/graphql/graphql-edge-proxy.test.ts
index c847d26d6d..b2a53976b4 100644
--- a/packages/sitecore-jss/src/graphql/graphql-edge-proxy.test.ts
+++ b/packages/sitecore-jss/src/graphql/graphql-edge-proxy.test.ts
@@ -11,7 +11,7 @@ describe('graphql-edge-proxy', () => {
       const url = getEdgeProxyContentUrl(sitecoreEdgeContextId);
 
       expect(url).to.equal(
-        `${SITECORE_EDGE_URL_DEFAULT}/content/api/graphql/v1?sitecoreContextId=0730fc5a-3333-5555-5555-08db6d7ddb49`
+        `${SITECORE_EDGE_URL_DEFAULT}/v1/content/api/graphql/v1?sitecoreContextId=0730fc5a-3333-5555-5555-08db6d7ddb49`
       );
     });
 
@@ -22,7 +22,7 @@ describe('graphql-edge-proxy', () => {
       const url = getEdgeProxyContentUrl(sitecoreEdgeContextId, sitecoreEdgeUrl);
 
       expect(url).to.equal(
-        'https://test.com/content/api/graphql/v1?sitecoreContextId=0730fc5a-3333-5555-5555-08db6d7ddb49'
+        'https://test.com/v1/content/api/graphql/v1?sitecoreContextId=0730fc5a-3333-5555-5555-08db6d7ddb49'
       );
     });
   });
diff --git a/packages/sitecore-jss/src/graphql/graphql-edge-proxy.ts b/packages/sitecore-jss/src/graphql/graphql-edge-proxy.ts
index b869b71944..abb0ce734b 100644
--- a/packages/sitecore-jss/src/graphql/graphql-edge-proxy.ts
+++ b/packages/sitecore-jss/src/graphql/graphql-edge-proxy.ts
@@ -9,4 +9,4 @@ import { SITECORE_EDGE_URL_DEFAULT } from '../constants';
 export const getEdgeProxyContentUrl = (
   sitecoreEdgeContextId: string,
   sitecoreEdgeUrl = SITECORE_EDGE_URL_DEFAULT
-) => `${sitecoreEdgeUrl}/content/api/graphql/v1?sitecoreContextId=${sitecoreEdgeContextId}`;
+) => `${sitecoreEdgeUrl}/v1/content/api/graphql/v1?sitecoreContextId=${sitecoreEdgeContextId}`;
diff --git a/packages/sitecore-jss/src/personalize/index.ts b/packages/sitecore-jss/src/personalize/index.ts
index 55363c3c2a..7f51a7fbf2 100644
--- a/packages/sitecore-jss/src/personalize/index.ts
+++ b/packages/sitecore-jss/src/personalize/index.ts
@@ -1,6 +1,6 @@
 export { personalizeLayout } from './layout-personalizer';
-export { PosResolver } from './pos-resolver';
 export {
+  PersonalizeInfo,
   GraphQLPersonalizeService,
   GraphQLPersonalizeServiceConfig,
 } from './graphql-personalize-service';
diff --git a/packages/sitecore-jss/src/personalize/pos-resolver.test.ts b/packages/sitecore-jss/src/personalize/pos-resolver.test.ts
deleted file mode 100644
index 25cea8c230..0000000000
--- a/packages/sitecore-jss/src/personalize/pos-resolver.test.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-import { expect } from 'chai';
-import { SiteInfo } from '../site';
-import { PosResolver } from './pos-resolver';
-
-describe('resolvePointOfSale', () => {
-  it('should return empty when no point of sale present', () => {
-    const site: SiteInfo = {
-      name: 'no-pos',
-      hostName: 'www.nopos.com',
-      language: 'en',
-    };
-    const language = 'en';
-    const result = PosResolver.resolve(site, language);
-    expect(result).to.equal('');
-  });
-
-  it('should return pos for provided language', () => {
-    const myPoint = 'apos.com';
-    const site: SiteInfo = {
-      name: 'apos',
-      hostName: 'www.apos.com',
-      pointOfSale: {
-        en: myPoint,
-      },
-      language: 'de-DE',
-    };
-
-    const result = PosResolver.resolve(site, 'en');
-    expect(result).to.equal(myPoint);
-  });
-
-  it('should use fallback wildcard value as first backup', () => {
-    const site: SiteInfo = {
-      name: 'apos',
-      hostName: 'www.apos.com',
-      pointOfSale: {
-        'de-DE': 'depos.com',
-        'es-ES': 'espos.com',
-        '*': 'fallpos.com',
-      },
-      language: 'de-DE',
-    };
-
-    const result = PosResolver.resolve(site, 'en');
-    expect(result).to.equal('fallpos.com');
-  });
-
-  it('should return pos for site language as second backup', () => {
-    const site: SiteInfo = {
-      name: 'apos',
-      hostName: 'www.apos.com',
-      pointOfSale: {
-        'de-DE': 'depos.com',
-        'es-ES': 'espos.com',
-      },
-      language: 'de-DE',
-    };
-
-    const result = PosResolver.resolve(site, 'en');
-    expect(result).to.equal('depos.com');
-  });
-
-  it('should return pos for site language when provided language is empty', () => {
-    const site: SiteInfo = {
-      name: 'apos',
-      hostName: 'www.apos.com',
-      pointOfSale: {
-        'de-DE': 'depos.com',
-        'es-ES': 'espos.com',
-      },
-      language: 'de-DE',
-    };
-
-    const result = PosResolver.resolve(site, '');
-    expect(result).to.equal('depos.com');
-  });
-});
diff --git a/packages/sitecore-jss/src/personalize/pos-resolver.ts b/packages/sitecore-jss/src/personalize/pos-resolver.ts
deleted file mode 100644
index 4c0e2e8510..0000000000
--- a/packages/sitecore-jss/src/personalize/pos-resolver.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { SiteInfo } from '../site';
-
-export class PosResolver {
-  static resolve = (site: SiteInfo, language: string) => {
-    return site.pointOfSale
-      ? site.pointOfSale[language] || site.pointOfSale['*'] || site.pointOfSale[site.language]
-      : '';
-  };
-}
diff --git a/packages/sitecore-jss/src/site/graphql-siteinfo-service.test.ts b/packages/sitecore-jss/src/site/graphql-siteinfo-service.test.ts
index 53f61b98a5..e1cdafd299 100644
--- a/packages/sitecore-jss/src/site/graphql-siteinfo-service.test.ts
+++ b/packages/sitecore-jss/src/site/graphql-siteinfo-service.test.ts
@@ -19,17 +19,14 @@ describe('GraphQLSiteInfoService', () => {
     name,
     hostName,
     language,
-    pointOfSale = '',
   }: {
     name: string;
     hostName: string;
     language: string;
-    pointOfSale: string;
   }): GraphQLSiteInfoResult => ({
     name: { value: name },
     hostName: { value: hostName },
     language: { value: language },
-    pointOfSale: { value: pointOfSale },
   });
 
   const nonEmptyResponse = ({
@@ -52,7 +49,6 @@ describe('GraphQLSiteInfoService', () => {
               name: `site ${start + n}`,
               hostName: 'restricted.gov',
               language: 'en',
-              pointOfSale: 'en=en-pos',
             })
           ),
           ...sites,
@@ -103,7 +99,6 @@ describe('GraphQLSiteInfoService', () => {
             name: 'public 0',
             hostName: 'pr.showercurtains.org',
             language: '',
-            pointOfSale: '',
           }),
         ],
       })
@@ -115,15 +110,11 @@ describe('GraphQLSiteInfoService', () => {
         name: 'site 0',
         hostName: 'restricted.gov',
         language: 'en',
-        pointOfSale: {
-          en: 'en-pos',
-        },
       },
       {
         name: 'public 0',
         hostName: 'pr.showercurtains.org',
         language: '',
-        pointOfSale: undefined,
       },
     ]);
   });
@@ -136,7 +127,6 @@ describe('GraphQLSiteInfoService', () => {
             name: 'public 0',
             hostName: 'pr.showercurtains.org',
             language: '',
-            pointOfSale: '',
           }),
         ],
       })
@@ -152,15 +142,11 @@ describe('GraphQLSiteInfoService', () => {
         name: 'site 0',
         hostName: 'restricted.gov',
         language: 'en',
-        pointOfSale: {
-          en: 'en-pos',
-        },
       },
       {
         name: 'public 0',
         hostName: 'pr.showercurtains.org',
         language: '',
-        pointOfSale: undefined,
       },
     ]);
   });
@@ -181,49 +167,31 @@ describe('GraphQLSiteInfoService', () => {
         name: 'site 0',
         hostName: 'restricted.gov',
         language: 'en',
-        pointOfSale: {
-          en: 'en-pos',
-        },
       },
       {
         name: 'site 1',
         hostName: 'restricted.gov',
         language: 'en',
-        pointOfSale: {
-          en: 'en-pos',
-        },
       },
       {
         name: 'site 2',
         hostName: 'restricted.gov',
         language: 'en',
-        pointOfSale: {
-          en: 'en-pos',
-        },
       },
       {
         name: 'site 3',
         hostName: 'restricted.gov',
         language: 'en',
-        pointOfSale: {
-          en: 'en-pos',
-        },
       },
       {
         name: 'site 4',
         hostName: 'restricted.gov',
         language: 'en',
-        pointOfSale: {
-          en: 'en-pos',
-        },
       },
       {
         name: 'site 5',
         hostName: 'restricted.gov',
         language: 'en',
-        pointOfSale: {
-          en: 'en-pos',
-        },
       },
     ]);
   });
@@ -257,7 +225,6 @@ describe('GraphQLSiteInfoService', () => {
             name: 'public 0',
             hostName: 'pr.showercurtains.org',
             language: '',
-            pointOfSale: '',
           }),
         ],
       })
@@ -273,15 +240,11 @@ describe('GraphQLSiteInfoService', () => {
         name: 'site 0',
         hostName: 'restricted.gov',
         language: 'en',
-        pointOfSale: {
-          en: 'en-pos',
-        },
       },
       {
         name: 'public 0',
         hostName: 'pr.showercurtains.org',
         language: '',
-        pointOfSale: undefined,
       },
     ]);
     nock.cleanAll();
diff --git a/packages/sitecore-jss/src/site/graphql-siteinfo-service.ts b/packages/sitecore-jss/src/site/graphql-siteinfo-service.ts
index c0b87758f4..b917fd6945 100644
--- a/packages/sitecore-jss/src/site/graphql-siteinfo-service.ts
+++ b/packages/sitecore-jss/src/site/graphql-siteinfo-service.ts
@@ -1,4 +1,3 @@
-import { URLSearchParams } from 'url';
 import { GraphQLClient, GraphQLRequestClient, PageInfo } from '../graphql';
 import debug from '../debug';
 import { CacheClient, CacheOptions, MemoryCacheClient } from '../cache-client';
@@ -34,9 +33,6 @@ const defaultQuery = /* GraphQL */ `
           language: field(name: "Language") {
             value
           }
-          pointOfSale: field(name: "POS") {
-            value
-          }
         }
       }
     }
@@ -60,10 +56,6 @@ export type SiteInfo = {
    * Site default language
    */
   language: string;
-  /**
-   * Site point of sale
-   */
-  pointOfSale?: Record<string, string>;
 };
 
 export type GraphQLSiteInfoServiceConfig = CacheOptions & {
@@ -107,9 +99,6 @@ export type GraphQLSiteInfoResult = {
   language: {
     value: string;
   };
-  pointOfSale?: {
-    value: string;
-  };
 };
 
 export class GraphQLSiteInfoService {
@@ -150,9 +139,6 @@ export class GraphQLSiteInfoService {
       });
       const result = response?.search?.results?.reduce<SiteInfo[]>((result, current) => {
         result.push({
-          pointOfSale: current.pointOfSale?.value
-            ? Object.fromEntries(new URLSearchParams(current.pointOfSale.value))
-            : undefined,
           name: current.name.value,
           hostName: current.hostName.value,
           language: current.language.value,
diff --git a/yarn.lock b/yarn.lock
index 7fdfc400dd..d81fa2365c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6433,6 +6433,32 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@sitecore-cloudsdk/core@npm:^0.1.0-rc.2":
+  version: 0.1.0-rc.4
+  resolution: "@sitecore-cloudsdk/core@npm:0.1.0-rc.4"
+  dependencies:
+    "@sitecore-cloudsdk/utils": ^0.1.0-rc.2
+  checksum: 596ebb923e8a7598b15c7762c6a8c3f7e6bc1fb9746e8ae51c656a7c3dd91a39e75b089abb8f4a1784f6dba2cf4115d9947f9fada26d6022191985acb4ee28a5
+  languageName: node
+  linkType: hard
+
+"@sitecore-cloudsdk/personalize@npm:^0.1.1":
+  version: 0.1.1
+  resolution: "@sitecore-cloudsdk/personalize@npm:0.1.1"
+  dependencies:
+    "@sitecore-cloudsdk/core": ^0.1.0-rc.2
+    "@sitecore-cloudsdk/utils": ^0.1.0-rc.2
+  checksum: e32a4f4b416a39c7657e475c49b6793ecc376a961e318cf3065ef148f78d6c00207ce2364d492a43ec5729322450a5faab0082ce3dafd580af4c26df9212530f
+  languageName: node
+  linkType: hard
+
+"@sitecore-cloudsdk/utils@npm:^0.1.0-rc.2":
+  version: 0.1.0-rc.4
+  resolution: "@sitecore-cloudsdk/utils@npm:0.1.0-rc.4"
+  checksum: 28bce2648560a6b9e0621228642cc590baddc3ad1c335acec9ba0c45934472c1a3455048f9d9e4a566f933044fb1cc39c8b59f0ec1e60e878e9337f4227b72e5
+  languageName: node
+  linkType: hard
+
 "@sitecore-feaas/clientside@npm:^0.4.12":
   version: 0.4.12
   resolution: "@sitecore-feaas/clientside@npm:0.4.12"
@@ -6620,10 +6646,10 @@ __metadata:
   version: 0.0.0-use.local
   resolution: "@sitecore-jss/sitecore-jss-nextjs@workspace:packages/sitecore-jss-nextjs"
   dependencies:
+    "@sitecore-cloudsdk/personalize": ^0.1.1
     "@sitecore-jss/sitecore-jss": 21.6.0-canary.26
     "@sitecore-jss/sitecore-jss-dev-tools": 21.6.0-canary.26
     "@sitecore-jss/sitecore-jss-react": 21.6.0-canary.26
-    "@sitecore/engage": ^1.4.1
     "@types/chai": ^4.3.4
     "@types/chai-as-promised": ^7.1.5
     "@types/chai-string": ^1.4.2
@@ -6663,7 +6689,8 @@ __metadata:
     ts-node: ^10.9.1
     typescript: ~4.9.4
   peerDependencies:
-    "@sitecore/engage": ^1.4.1
+    "@sitecore-cloudsdk/events": ^0.1.1
+    "@sitecore-cloudsdk/personalize": ^0.1.1
     next: ^13.4.16
     react: ^18.2.0
     react-dom: ^18.2.0
@@ -6914,13 +6941,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@sitecore/engage@npm:^1.4.1":
-  version: 1.4.1
-  resolution: "@sitecore/engage@npm:1.4.1"
-  checksum: 582b7a55ba407765def12518114790fb1735c359e60fe4594102a5e643539b148a494b02bf71970bcafc807b92fe19a1ab8ff7c2af3db2c080ab36ec2eb16d57
-  languageName: node
-  linkType: hard
-
 "@socket.io/component-emitter@npm:~3.1.0":
   version: 3.1.0
   resolution: "@socket.io/component-emitter@npm:3.1.0"