personalize-connect-sdk 1.3.1 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Personalize Connect SDK
2
2
 
3
- A lightweight Next.js package that bridges Sitecore Personalize Interactive Experiences with XM Cloud component datasources at runtime. The SDK reads configuration authored by the Marketplace app, calls Personalize for a decision, and swaps component content accordingly — with zero per-component code.
3
+ Runtime SDK for [Personalize Connect](https://github.com/Sitecore-Hackathon/2026-Team-Solo) a zero-code bridge between Sitecore XM Cloud components and Sitecore Personalize Full Stack Interactive Experiences.
4
+
5
+ The SDK reads configuration authored by the Marketplace app (stored in the content tree), calls Personalize for a decision via the Edge proxy, resolves the matching datasource from Experience Edge, and swaps component content — with zero per-component code. In Page Builder, components with personalization get a visual indicator.
4
6
 
5
7
  ## Installation
6
8
 
@@ -10,23 +12,21 @@ npm install personalize-connect-sdk
10
12
 
11
13
  Peer dependency: `react` >= 18.
12
14
 
13
- ## Usage
15
+ ## Quick Start (XM Cloud)
14
16
 
15
17
  ### 1. Wrap your app with `PersonalizeProvider`
16
18
 
19
+ In `_app.tsx` (Pages Router) or `layout.tsx` (App Router):
20
+
17
21
  ```tsx
18
22
  import { PersonalizeProvider } from "personalize-connect-sdk";
19
23
 
20
- export default function RootLayout({ children }) {
24
+ export default function App({ children }) {
21
25
  return (
22
26
  <PersonalizeProvider
23
- clientKey={process.env.NEXT_PUBLIC_PERSONALIZE_CLIENT_KEY!}
24
- pointOfSale={process.env.NEXT_PUBLIC_PERSONALIZE_POINT_OF_SALE!}
25
- resolveDatasource={async (datasourceId) => {
26
- // Fetch datasource fields via Experience Edge GraphQL or Layout Service
27
- const res = await fetch(`/api/datasource/${datasourceId}`);
28
- return res.json();
29
- }}
27
+ sitecoreEdgeContextId={process.env.SITECORE_EDGE_CONTEXT_ID}
28
+ siteName={process.env.SITECORE_SITE_NAME}
29
+ debug // remove in production
30
30
  >
31
31
  {children}
32
32
  </PersonalizeProvider>
@@ -34,49 +34,152 @@ export default function RootLayout({ children }) {
34
34
  }
35
35
  ```
36
36
 
37
+ That's it for provider setup. One prop (`sitecoreEdgeContextId`) drives everything:
38
+
39
+ - **Browser ID** — fetched from `edge-platform.sitecorecloud.io/v1/init`
40
+ - **Personalize calls** — routed through the Edge proxy (`/v1/personalize`)
41
+ - **Datasource resolution** — built-in via Edge proxy GraphQL
42
+ - **Config loading** — auto-discovered from the content tree via Edge
43
+ - **Editing detection** — auto-detected from JSS Sitecore context
44
+
37
45
  ### 2. Wrap components with `withPersonalizeConnect`
38
46
 
39
47
  ```tsx
40
48
  import { withPersonalizeConnect } from "personalize-connect-sdk";
41
- import MyComponent from "./MyComponent";
42
49
 
43
- // Config is read from props.rendering.personalizeConnect (or customize via getConfig)
44
- export default withPersonalizeConnect(MyComponent);
50
+ const PromoCard = ({ fields }) => (
51
+ <div>
52
+ <h2>{fields?.title?.value}</h2>
53
+ <p>{fields?.body?.value}</p>
54
+ </div>
55
+ );
56
+
57
+ export default withPersonalizeConnect(PromoCard);
45
58
  ```
46
59
 
47
- The HOC renders immediately with the default datasource, calls Personalize asynchronously, and re-renders with personalized content when resolved. No changes needed inside the component.
60
+ The HOC:
61
+ 1. Looks up config from the content tree (loaded by the provider on mount)
62
+ 2. Renders with the default datasource immediately
63
+ 3. Calls Personalize asynchronously for a content decision
64
+ 4. Resolves the matching datasource from Experience Edge
65
+ 5. Re-renders with personalized `fields`
66
+ 6. In Page Builder, shows a visual indicator (purple border + badge)
48
67
 
49
68
  ### 3. Or use the `usePersonalizeExperience` hook
50
69
 
51
70
  ```tsx
52
71
  import { usePersonalizeExperience } from "personalize-connect-sdk";
53
72
 
54
- function MyComponent({ personalizeConnect }) {
55
- const { contentKey, resolvedFields, isLoading, error } = usePersonalizeExperience(personalizeConnect);
73
+ function MyComponent({ rendering }) {
74
+ const config = /* get config from context or props */;
75
+ const { contentKey, resolvedFields, isLoading, error } = usePersonalizeExperience(config);
56
76
 
57
77
  if (isLoading) return <Skeleton />;
58
- return <div>{resolvedFields?.heading}</div>;
78
+ return <div>{resolvedFields?.heading?.value}</div>;
59
79
  }
60
80
  ```
61
81
 
62
- ## Config shape
82
+ ## Provider Props
83
+
84
+ ### XM Cloud (recommended)
85
+
86
+ | Prop | Required | Description |
87
+ |------|----------|-------------|
88
+ | `sitecoreEdgeContextId` | Yes | Edge Context ID — drives all Edge proxy calls |
89
+ | `siteName` | Yes | XM Cloud site name |
90
+ | `sitecoreEdgeUrl` | No | Edge platform URL (defaults to `https://edge-platform.sitecorecloud.io`) |
91
+
92
+ ### Legacy (direct credentials)
93
+
94
+ | Prop | Required | Description |
95
+ |------|----------|-------------|
96
+ | `clientKey` | Yes | Personalize API client key |
97
+ | `pointOfSale` | Yes | Point of sale identifier |
98
+ | `edgeUrl` | No | Experience Edge GraphQL endpoint |
99
+ | `apiKey` | No | Sitecore API key for Edge |
100
+
101
+ ### Common
102
+
103
+ | Prop | Default | Description |
104
+ |------|---------|-------------|
105
+ | `channel` | `"WEB"` | Channel for Personalize calls |
106
+ | `language` | `"EN"` | Language code |
107
+ | `currencyCode` | `"USD"` | Currency code |
108
+ | `timeout` | `600` | Personalize call timeout (ms) |
109
+ | `debug` | `false` | Enable `[PersonalizeConnect]` console logging |
110
+ | `isEditing` | auto | Override Page Builder editing detection |
111
+ | `sitePath` | auto | Override site root path auto-discovery |
112
+ | `resolveDatasource` | built-in | Custom datasource resolver (overrides built-in Edge resolution) |
113
+
114
+ ## How Config Loading Works
115
+
116
+ The Marketplace app stores configs in the content tree at:
117
+
118
+ ```
119
+ {sitePath}/Data/PersonalizeConnect/{pageItemId}/config-{renderingId}
120
+ ```
63
121
 
64
- Config is attached to each rendering in XMC layout data (authored by the Marketplace app):
122
+ On mount, the SDK:
123
+ 1. Reads the page item ID from `__NEXT_DATA__` (JSS layout data)
124
+ 2. Queries Edge for the page item's content tree path
125
+ 3. Derives the site root path (first 4 path segments)
126
+ 4. Fetches all config children for that page in one GraphQL query
127
+ 5. Caches them in context, keyed by rendering instance ID
128
+
129
+ Each HOC looks up its config via `props.rendering.uid`. No config on the rendering means no personalization — the component renders normally.
130
+
131
+ ## Config Shape
132
+
133
+ Authored by the Marketplace app, stored as JSON in the content tree:
65
134
 
66
135
  ```ts
67
136
  interface PersonalizeConnectConfig {
68
- friendlyId: string; // Personalize Interactive Experience ID
137
+ friendlyId: string; // Personalize Interactive Experience ID
69
138
  contentMap: Record<string, string>; // contentKey -> datasource GUID
70
- defaultKey: string; // Fallback key if experience fails
139
+ defaultKey: string; // Fallback key
71
140
  }
72
141
  ```
73
142
 
143
+ ## Debug Logging
144
+
145
+ Pass `debug` to the provider to trace the full flow in the browser console:
146
+
147
+ ```
148
+ [PersonalizeConnect] Provider mounting { mode: 'Context ID', ... }
149
+ [PersonalizeConnect] BrowserId (edge): from cookie abc123...
150
+ [PersonalizeConnect] Config loader: Auto-discovered site path: /sitecore/content/company/company
151
+ [PersonalizeConnect] Config loader: loaded config for rendering xyz → experience homepage_promo
152
+ [PersonalizeConnect] [PromoCard] Config active: { friendlyId: 'homepage_promo', ... }
153
+ [PersonalizeConnect] callPersonalize [homepage_promo] → contentKey: returning-visitor
154
+ [PersonalizeConnect] [PromoCard] Fields resolved — swapping props.fields
155
+ ```
156
+
74
157
  ## Exports
75
158
 
76
- - `PersonalizeProvider`, `usePersonalizeContext` — Provider and context
77
- - `withPersonalizeConnect` — HOC for zero-code personalization
159
+ **Provider & Context**
160
+ - `PersonalizeProvider` — Wrap your app
161
+ - `usePersonalizeContext` — Access context directly
162
+
163
+ **HOC & Hook**
164
+ - `withPersonalizeConnect` — Zero-code personalization HOC
78
165
  - `usePersonalizeExperience` — Hook for manual control
79
- - `callPersonalize` — Low-level API client
80
- - `resolveContent` — Map contentKey to datasource fields
81
- - `getBrowserId` — Browser ID cookie helper
82
- - Types: `PersonalizeConnectConfig`, `PersonalizeConnectProviderProps`, etc.
166
+
167
+ **Config**
168
+ - `loadPageConfigs` — Load configs from Edge (used internally, exported for advanced use)
169
+
170
+ **Edge Resolution**
171
+ - `createEdgeResolver` — Direct Edge GraphQL resolver (legacy)
172
+ - `createEdgeProxyResolver` — Edge proxy resolver (Context ID mode)
173
+
174
+ **Browser ID**
175
+ - `getBrowserId` — Legacy local cookie
176
+ - `getEdgeBrowserId` — Edge proxy init
177
+
178
+ **Editing**
179
+ - `isEditingMode` — Page Builder detection
180
+
181
+ **Debug**
182
+ - `setDebug`, `isDebugEnabled` — Control logging
183
+
184
+ **Types**
185
+ - `PersonalizeConnectConfig`, `PersonalizeConnectProviderProps`, `PersonalizeContextValue`, `ComponentFields`, `CallFlowsRequest`, etc.
package/dist/index.js CHANGED
@@ -43,7 +43,7 @@ module.exports = __toCommonJS(index_exports);
43
43
  var import_react = require("react");
44
44
 
45
45
  // src/logger.ts
46
- var PREFIX = "[PersonalizeConnect]";
46
+ var PREFIX = "[PersonalizeConnectSDK]";
47
47
  var enabled = false;
48
48
  function setDebug(on) {
49
49
  enabled = on;
@@ -397,6 +397,7 @@ async function loadPageConfigs(edgeUrl, pageItemId, language, headers = {}, site
397
397
  error("Config loader fetch error:", e);
398
398
  }
399
399
  groupEnd();
400
+ log("Config loader: result", Object.fromEntries(configs));
400
401
  return configs;
401
402
  }
402
403
 
@@ -778,7 +779,7 @@ function withPersonalizeConnect(WrappedComponent, getConfig = DEFAULT_GET_CONFIG
778
779
  });
779
780
  config = fromContext;
780
781
  } else if (context.configsLoaded) {
781
- log(`[${componentName}] No config in context for rendering uid ${normalizedUid} \u2014 passthrough`);
782
+ log(`[${componentName}] No config match for uid "${normalizedUid}". All configs:`, Object.fromEntries(context.configs));
782
783
  } else {
783
784
  log(`[${componentName}] Configs still loading for uid ${normalizedUid}...`);
784
785
  }
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
3
3
 
4
4
  // src/logger.ts
5
- var PREFIX = "[PersonalizeConnect]";
5
+ var PREFIX = "[PersonalizeConnectSDK]";
6
6
  var enabled = false;
7
7
  function setDebug(on) {
8
8
  enabled = on;
@@ -356,6 +356,7 @@ async function loadPageConfigs(edgeUrl, pageItemId, language, headers = {}, site
356
356
  error("Config loader fetch error:", e);
357
357
  }
358
358
  groupEnd();
359
+ log("Config loader: result", Object.fromEntries(configs));
359
360
  return configs;
360
361
  }
361
362
 
@@ -737,7 +738,7 @@ function withPersonalizeConnect(WrappedComponent, getConfig = DEFAULT_GET_CONFIG
737
738
  });
738
739
  config = fromContext;
739
740
  } else if (context.configsLoaded) {
740
- log(`[${componentName}] No config in context for rendering uid ${normalizedUid} \u2014 passthrough`);
741
+ log(`[${componentName}] No config match for uid "${normalizedUid}". All configs:`, Object.fromEntries(context.configs));
741
742
  } else {
742
743
  log(`[${componentName}] Configs still loading for uid ${normalizedUid}...`);
743
744
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "personalize-connect-sdk",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "description": "Runtime SDK for Personalize Connect - resolves active experience outcomes and datasources in your rendering host",
5
5
  "author": "Dylan Young",
6
6
  "keywords": [
@@ -14,7 +14,7 @@
14
14
  "license": "MIT",
15
15
  "repository": {
16
16
  "type": "git",
17
- "url": "https://github.com/2026-Team-Solo/2026-Team-Solo.git",
17
+ "url": "https://github.com/Sitecore-Hackathon/2026-Team-Solo.git",
18
18
  "directory": "packages/sdk"
19
19
  },
20
20
  "main": "dist/index.js",