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 +130 -27
- package/dist/index.js +3 -2
- package/dist/index.mjs +3 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Personalize Connect SDK
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
##
|
|
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
|
|
24
|
+
export default function App({ children }) {
|
|
21
25
|
return (
|
|
22
26
|
<PersonalizeProvider
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
44
|
-
|
|
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
|
|
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({
|
|
55
|
-
const
|
|
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
|
-
##
|
|
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
|
-
|
|
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;
|
|
137
|
+
friendlyId: string; // Personalize Interactive Experience ID
|
|
69
138
|
contentMap: Record<string, string>; // contentKey -> datasource GUID
|
|
70
|
-
defaultKey: string;
|
|
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
|
-
|
|
77
|
-
- `
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
- `
|
|
82
|
-
|
|
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 = "[
|
|
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
|
|
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 = "[
|
|
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
|
|
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.
|
|
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/
|
|
17
|
+
"url": "https://github.com/Sitecore-Hackathon/2026-Team-Solo.git",
|
|
18
18
|
"directory": "packages/sdk"
|
|
19
19
|
},
|
|
20
20
|
"main": "dist/index.js",
|