@sitecore-jss/sitecore-jss-nextjs 22.1.0-canary.58 → 22.1.0-canary.59

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.
@@ -18,6 +18,18 @@ class MiddlewareBase {
18
18
  var _a, _b;
19
19
  return !!(((_a = req.cookies.get('__prerender_bypass')) === null || _a === void 0 ? void 0 : _a.value) || ((_b = req.cookies.get('__next_preview_data')) === null || _b === void 0 ? void 0 : _b.value));
20
20
  }
21
+ /**
22
+ * Determines if the request is a Next.js (next/link) prefetch request
23
+ * @param {NextRequest} req request
24
+ * @returns {boolean} is prefetch
25
+ */
26
+ isPrefetch(req) {
27
+ return (
28
+ // eslint-disable-next-line prettier/prettier
29
+ req.headers.get('purpose') === 'prefetch' || // Pages Router
30
+ req.headers.get('Next-Router-Prefetch') === '1' // App Router
31
+ );
32
+ }
21
33
  excludeRoute(pathname) {
22
34
  var _a, _b;
23
35
  return (pathname.startsWith('/api/') || // Ignore Next.js API calls
@@ -61,6 +61,15 @@ class PersonalizeMiddleware extends middleware_1.MiddlewareBase {
61
61
  sitecore_jss_1.debug.personalize('skipped (no personalization configured)');
62
62
  return response;
63
63
  }
64
+ if (this.isPrefetch(req)) {
65
+ sitecore_jss_1.debug.personalize('skipped (prefetch)');
66
+ // Personalized, but this is a prefetch request.
67
+ // In this case, don't execute a personalize request; otherwise, the metrics for component A/B experiments would be inaccurate.
68
+ // Disable preflight caching to force revalidation on client-side navigation (personalization WILL be influenced).
69
+ // Note the reason we don't move this any earlier in the middleware is that we would then be sacrificing performance for non-personalized pages.
70
+ response.headers.set('x-middleware-cache', 'no-cache');
71
+ return response;
72
+ }
64
73
  yield this.initPersonalizeServer({
65
74
  hostname,
66
75
  siteName: site.name,
@@ -68,32 +77,36 @@ class PersonalizeMiddleware extends middleware_1.MiddlewareBase {
68
77
  response,
69
78
  });
70
79
  const params = this.getExperienceParams(req);
71
- sitecore_jss_1.debug.personalize('executing experience for %s %o', personalizeInfo.contentId, params);
72
- let variantId;
73
- // Execute targeted experience in Personalize SDK
74
- // eslint-disable-next-line no-useless-catch
75
- try {
76
- const personalization = yield this.personalize({ personalizeInfo, params, language, timeout }, req);
77
- variantId = personalization.variantId;
78
- }
79
- catch (error) {
80
- throw error;
81
- }
82
- if (!variantId) {
83
- sitecore_jss_1.debug.personalize('skipped (no variant identified)');
84
- return response;
85
- }
86
- if (!personalizeInfo.variantIds.includes(variantId)) {
87
- sitecore_jss_1.debug.personalize('skipped (invalid variant)');
80
+ const executions = this.getPersonalizeExecutions(personalizeInfo, language);
81
+ const identifiedVariantIds = [];
82
+ yield Promise.all(executions.map((execution) => this.personalize({
83
+ friendlyId: execution.friendlyId,
84
+ variantIds: execution.variantIds,
85
+ params,
86
+ language,
87
+ timeout,
88
+ }, req).then((personalization) => {
89
+ const variantId = personalization.variantId;
90
+ if (variantId) {
91
+ if (!execution.variantIds.includes(variantId)) {
92
+ sitecore_jss_1.debug.personalize('invalid variant %s', variantId);
93
+ }
94
+ else {
95
+ identifiedVariantIds.push(variantId);
96
+ }
97
+ }
98
+ })));
99
+ if (identifiedVariantIds.length === 0) {
100
+ sitecore_jss_1.debug.personalize('skipped (no variant(s) identified)');
88
101
  return response;
89
102
  }
90
103
  // Path can be rewritten by previously executed middleware
91
104
  const basePath = (res === null || res === void 0 ? void 0 : res.headers.get('x-sc-rewrite')) || pathname;
92
105
  // Rewrite to persononalized path
93
- const rewritePath = (0, personalize_1.getPersonalizedRewrite)(basePath, { variantId });
106
+ const rewritePath = (0, personalize_1.getPersonalizedRewrite)(basePath, identifiedVariantIds);
94
107
  response = this.rewrite(rewritePath, req, response);
95
- // Disable preflight caching to force revalidation on client-side navigation (personalization may be influenced)
96
- // See https://github.com/vercel/next.js/issues/32727
108
+ // Disable preflight caching to force revalidation on client-side navigation (personalization MAY be influenced).
109
+ // See https://github.com/vercel/next.js/pull/32767
97
110
  response.headers.set('x-middleware-cache', 'no-cache');
98
111
  sitecore_jss_1.debug.personalize('personalize middleware end in %dms: %o', Date.now() - startTimestamp, {
99
112
  rewritePath,
@@ -132,17 +145,18 @@ class PersonalizeMiddleware extends middleware_1.MiddlewareBase {
132
145
  });
133
146
  });
134
147
  }
135
- personalize({ params, personalizeInfo, language, timeout, }, request) {
148
+ personalize({ params, friendlyId, language, timeout, variantIds, }, request) {
136
149
  var _a;
137
150
  return __awaiter(this, void 0, void 0, function* () {
138
- const personalizationData = {
151
+ sitecore_jss_1.debug.personalize('executing experience for %s %o', friendlyId, params);
152
+ return (yield (0, server_2.personalize)(request, {
139
153
  channel: this.config.cdpConfig.channel || 'WEB',
140
154
  currency: (_a = this.config.cdpConfig.currency) !== null && _a !== void 0 ? _a : 'USD',
141
- friendlyId: personalizeInfo.contentId,
155
+ friendlyId,
142
156
  params,
143
157
  language,
144
- };
145
- return (yield (0, server_2.personalize)(request, personalizationData, { timeout }));
158
+ pageVariantIds: variantIds,
159
+ }, { timeout }));
146
160
  });
147
161
  }
148
162
  getExperienceParams(req) {
@@ -164,5 +178,51 @@ class PersonalizeMiddleware extends middleware_1.MiddlewareBase {
164
178
  // ignore files
165
179
  return pathname.includes('.') || super.excludeRoute(pathname);
166
180
  }
181
+ /**
182
+ * Aggregates personalize executions based on the provided route personalize information and language
183
+ * @param {PersonalizeInfo} personalizeInfo the route personalize information
184
+ * @param {string} language the language
185
+ * @returns An array of personalize executions
186
+ */
187
+ getPersonalizeExecutions(personalizeInfo, language) {
188
+ if (personalizeInfo.variantIds.length === 0) {
189
+ return [];
190
+ }
191
+ const results = [];
192
+ return personalizeInfo.variantIds.reduce((results, variantId) => {
193
+ if (variantId.includes('_')) {
194
+ // Component-level personalization in format "<ComponentID>_<VariantID>"
195
+ const componentId = variantId.split('_')[0];
196
+ const friendlyId = personalize_1.CdpHelper.getComponentFriendlyId(personalizeInfo.pageId, componentId, language, this.config.scope || this.config.edgeConfig.scope);
197
+ const execution = results.find((x) => x.friendlyId === friendlyId);
198
+ if (execution) {
199
+ execution.variantIds.push(variantId);
200
+ }
201
+ else {
202
+ // The default/control variant (format "<ComponentID>_default") is also a valid value returned by the execution
203
+ const defaultVariant = `${componentId}${personalize_1.DEFAULT_VARIANT}`;
204
+ results.push({
205
+ friendlyId,
206
+ variantIds: [defaultVariant, variantId],
207
+ });
208
+ }
209
+ }
210
+ else {
211
+ // Embedded (page-level) personalization in format "<VariantID>"
212
+ const friendlyId = personalize_1.CdpHelper.getPageFriendlyId(personalizeInfo.pageId, language, this.config.scope || this.config.edgeConfig.scope);
213
+ const execution = results.find((x) => x.friendlyId === friendlyId);
214
+ if (execution) {
215
+ execution.variantIds.push(variantId);
216
+ }
217
+ else {
218
+ results.push({
219
+ friendlyId,
220
+ variantIds: [variantId],
221
+ });
222
+ }
223
+ }
224
+ return results;
225
+ }, results);
226
+ }
167
227
  }
168
228
  exports.PersonalizeMiddleware = PersonalizeMiddleware;
@@ -148,13 +148,14 @@ class BaseGraphQLSitemapService {
148
148
  const formatPath = (path) => formatStaticPath(path.replace(/^\/|\/$/g, '').split('/'), language);
149
149
  const aggregatedPaths = [];
150
150
  sitePaths.forEach((item) => {
151
- var _a, _b, _c, _d;
151
+ var _a, _b, _c;
152
152
  if (!item)
153
153
  return;
154
154
  aggregatedPaths.push(formatPath(item.path));
155
- // check for type safety's sake - personalize may be empty depending on query type
156
- if ((_b = (_a = item.route) === null || _a === void 0 ? void 0 : _a.personalization) === null || _b === void 0 ? void 0 : _b.variantIds.length) {
157
- aggregatedPaths.push(...(((_d = (_c = item.route) === null || _c === void 0 ? void 0 : _c.personalization) === null || _d === void 0 ? void 0 : _d.variantIds.map((varId) => formatPath((0, personalize_1.getPersonalizedRewrite)(item.path, { variantId: varId })))) || {}));
155
+ const variantIds = (_c = (_b = (_a = item.route) === null || _a === void 0 ? void 0 : _a.personalization) === null || _b === void 0 ? void 0 : _b.variantIds) === null || _c === void 0 ? void 0 : _c.filter((variantId) => !variantId.includes('_') // exclude component A/B test variants
156
+ );
157
+ if (variantIds === null || variantIds === void 0 ? void 0 : variantIds.length) {
158
+ aggregatedPaths.push(...variantIds.map((varId) => formatPath((0, personalize_1.getPersonalizedRewrite)(item.path, [varId]))));
158
159
  }
159
160
  });
160
161
  return aggregatedPaths;
@@ -15,6 +15,18 @@ export class MiddlewareBase {
15
15
  var _a, _b;
16
16
  return !!(((_a = req.cookies.get('__prerender_bypass')) === null || _a === void 0 ? void 0 : _a.value) || ((_b = req.cookies.get('__next_preview_data')) === null || _b === void 0 ? void 0 : _b.value));
17
17
  }
18
+ /**
19
+ * Determines if the request is a Next.js (next/link) prefetch request
20
+ * @param {NextRequest} req request
21
+ * @returns {boolean} is prefetch
22
+ */
23
+ isPrefetch(req) {
24
+ return (
25
+ // eslint-disable-next-line prettier/prettier
26
+ req.headers.get('purpose') === 'prefetch' || // Pages Router
27
+ req.headers.get('Next-Router-Prefetch') === '1' // App Router
28
+ );
29
+ }
18
30
  excludeRoute(pathname) {
19
31
  var _a, _b;
20
32
  return (pathname.startsWith('/api/') || // Ignore Next.js API calls
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { NextResponse } from 'next/server';
11
- import { GraphQLPersonalizeService, getPersonalizedRewrite, } from '@sitecore-jss/sitecore-jss/personalize';
11
+ import { GraphQLPersonalizeService, getPersonalizedRewrite, CdpHelper, DEFAULT_VARIANT, } from '@sitecore-jss/sitecore-jss/personalize';
12
12
  import { debug } from '@sitecore-jss/sitecore-jss';
13
13
  import { MiddlewareBase } from './middleware';
14
14
  import { init, personalize } from '@sitecore-cloudsdk/personalize/server';
@@ -58,6 +58,15 @@ export class PersonalizeMiddleware extends MiddlewareBase {
58
58
  debug.personalize('skipped (no personalization configured)');
59
59
  return response;
60
60
  }
61
+ if (this.isPrefetch(req)) {
62
+ debug.personalize('skipped (prefetch)');
63
+ // Personalized, but this is a prefetch request.
64
+ // In this case, don't execute a personalize request; otherwise, the metrics for component A/B experiments would be inaccurate.
65
+ // Disable preflight caching to force revalidation on client-side navigation (personalization WILL be influenced).
66
+ // Note the reason we don't move this any earlier in the middleware is that we would then be sacrificing performance for non-personalized pages.
67
+ response.headers.set('x-middleware-cache', 'no-cache');
68
+ return response;
69
+ }
61
70
  yield this.initPersonalizeServer({
62
71
  hostname,
63
72
  siteName: site.name,
@@ -65,32 +74,36 @@ export class PersonalizeMiddleware extends MiddlewareBase {
65
74
  response,
66
75
  });
67
76
  const params = this.getExperienceParams(req);
68
- debug.personalize('executing experience for %s %o', personalizeInfo.contentId, params);
69
- let variantId;
70
- // Execute targeted experience in Personalize SDK
71
- // eslint-disable-next-line no-useless-catch
72
- try {
73
- const personalization = yield this.personalize({ personalizeInfo, params, language, timeout }, req);
74
- variantId = personalization.variantId;
75
- }
76
- catch (error) {
77
- throw error;
78
- }
79
- if (!variantId) {
80
- debug.personalize('skipped (no variant identified)');
81
- return response;
82
- }
83
- if (!personalizeInfo.variantIds.includes(variantId)) {
84
- debug.personalize('skipped (invalid variant)');
77
+ const executions = this.getPersonalizeExecutions(personalizeInfo, language);
78
+ const identifiedVariantIds = [];
79
+ yield Promise.all(executions.map((execution) => this.personalize({
80
+ friendlyId: execution.friendlyId,
81
+ variantIds: execution.variantIds,
82
+ params,
83
+ language,
84
+ timeout,
85
+ }, req).then((personalization) => {
86
+ const variantId = personalization.variantId;
87
+ if (variantId) {
88
+ if (!execution.variantIds.includes(variantId)) {
89
+ debug.personalize('invalid variant %s', variantId);
90
+ }
91
+ else {
92
+ identifiedVariantIds.push(variantId);
93
+ }
94
+ }
95
+ })));
96
+ if (identifiedVariantIds.length === 0) {
97
+ debug.personalize('skipped (no variant(s) identified)');
85
98
  return response;
86
99
  }
87
100
  // Path can be rewritten by previously executed middleware
88
101
  const basePath = (res === null || res === void 0 ? void 0 : res.headers.get('x-sc-rewrite')) || pathname;
89
102
  // Rewrite to persononalized path
90
- const rewritePath = getPersonalizedRewrite(basePath, { variantId });
103
+ const rewritePath = getPersonalizedRewrite(basePath, identifiedVariantIds);
91
104
  response = this.rewrite(rewritePath, req, response);
92
- // Disable preflight caching to force revalidation on client-side navigation (personalization may be influenced)
93
- // See https://github.com/vercel/next.js/issues/32727
105
+ // Disable preflight caching to force revalidation on client-side navigation (personalization MAY be influenced).
106
+ // See https://github.com/vercel/next.js/pull/32767
94
107
  response.headers.set('x-middleware-cache', 'no-cache');
95
108
  debug.personalize('personalize middleware end in %dms: %o', Date.now() - startTimestamp, {
96
109
  rewritePath,
@@ -129,17 +142,18 @@ export class PersonalizeMiddleware extends MiddlewareBase {
129
142
  });
130
143
  });
131
144
  }
132
- personalize({ params, personalizeInfo, language, timeout, }, request) {
145
+ personalize({ params, friendlyId, language, timeout, variantIds, }, request) {
133
146
  var _a;
134
147
  return __awaiter(this, void 0, void 0, function* () {
135
- const personalizationData = {
148
+ debug.personalize('executing experience for %s %o', friendlyId, params);
149
+ return (yield personalize(request, {
136
150
  channel: this.config.cdpConfig.channel || 'WEB',
137
151
  currency: (_a = this.config.cdpConfig.currency) !== null && _a !== void 0 ? _a : 'USD',
138
- friendlyId: personalizeInfo.contentId,
152
+ friendlyId,
139
153
  params,
140
154
  language,
141
- };
142
- return (yield personalize(request, personalizationData, { timeout }));
155
+ pageVariantIds: variantIds,
156
+ }, { timeout }));
143
157
  });
144
158
  }
145
159
  getExperienceParams(req) {
@@ -161,4 +175,50 @@ export class PersonalizeMiddleware extends MiddlewareBase {
161
175
  // ignore files
162
176
  return pathname.includes('.') || super.excludeRoute(pathname);
163
177
  }
178
+ /**
179
+ * Aggregates personalize executions based on the provided route personalize information and language
180
+ * @param {PersonalizeInfo} personalizeInfo the route personalize information
181
+ * @param {string} language the language
182
+ * @returns An array of personalize executions
183
+ */
184
+ getPersonalizeExecutions(personalizeInfo, language) {
185
+ if (personalizeInfo.variantIds.length === 0) {
186
+ return [];
187
+ }
188
+ const results = [];
189
+ return personalizeInfo.variantIds.reduce((results, variantId) => {
190
+ if (variantId.includes('_')) {
191
+ // Component-level personalization in format "<ComponentID>_<VariantID>"
192
+ const componentId = variantId.split('_')[0];
193
+ const friendlyId = CdpHelper.getComponentFriendlyId(personalizeInfo.pageId, componentId, language, this.config.scope || this.config.edgeConfig.scope);
194
+ const execution = results.find((x) => x.friendlyId === friendlyId);
195
+ if (execution) {
196
+ execution.variantIds.push(variantId);
197
+ }
198
+ else {
199
+ // The default/control variant (format "<ComponentID>_default") is also a valid value returned by the execution
200
+ const defaultVariant = `${componentId}${DEFAULT_VARIANT}`;
201
+ results.push({
202
+ friendlyId,
203
+ variantIds: [defaultVariant, variantId],
204
+ });
205
+ }
206
+ }
207
+ else {
208
+ // Embedded (page-level) personalization in format "<VariantID>"
209
+ const friendlyId = CdpHelper.getPageFriendlyId(personalizeInfo.pageId, language, this.config.scope || this.config.edgeConfig.scope);
210
+ const execution = results.find((x) => x.friendlyId === friendlyId);
211
+ if (execution) {
212
+ execution.variantIds.push(variantId);
213
+ }
214
+ else {
215
+ results.push({
216
+ friendlyId,
217
+ variantIds: [variantId],
218
+ });
219
+ }
220
+ }
221
+ return results;
222
+ }, results);
223
+ }
164
224
  }
@@ -144,13 +144,14 @@ export class BaseGraphQLSitemapService {
144
144
  const formatPath = (path) => formatStaticPath(path.replace(/^\/|\/$/g, '').split('/'), language);
145
145
  const aggregatedPaths = [];
146
146
  sitePaths.forEach((item) => {
147
- var _a, _b, _c, _d;
147
+ var _a, _b, _c;
148
148
  if (!item)
149
149
  return;
150
150
  aggregatedPaths.push(formatPath(item.path));
151
- // check for type safety's sake - personalize may be empty depending on query type
152
- if ((_b = (_a = item.route) === null || _a === void 0 ? void 0 : _a.personalization) === null || _b === void 0 ? void 0 : _b.variantIds.length) {
153
- aggregatedPaths.push(...(((_d = (_c = item.route) === null || _c === void 0 ? void 0 : _c.personalization) === null || _d === void 0 ? void 0 : _d.variantIds.map((varId) => formatPath(getPersonalizedRewrite(item.path, { variantId: varId })))) || {}));
151
+ const variantIds = (_c = (_b = (_a = item.route) === null || _a === void 0 ? void 0 : _a.personalization) === null || _b === void 0 ? void 0 : _b.variantIds) === null || _c === void 0 ? void 0 : _c.filter((variantId) => !variantId.includes('_') // exclude component A/B test variants
152
+ );
153
+ if (variantIds === null || variantIds === void 0 ? void 0 : variantIds.length) {
154
+ aggregatedPaths.push(...variantIds.map((varId) => formatPath(getPersonalizedRewrite(item.path, [varId]))));
154
155
  }
155
156
  });
156
157
  return aggregatedPaths;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sitecore-jss/sitecore-jss-nextjs",
3
- "version": "22.1.0-canary.58",
3
+ "version": "22.1.0-canary.59",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "sideEffects": false,
@@ -29,7 +29,7 @@
29
29
  "url": "https://github.com/sitecore/jss/issues"
30
30
  },
31
31
  "devDependencies": {
32
- "@sitecore-cloudsdk/personalize": "^0.3.0",
32
+ "@sitecore-cloudsdk/personalize": "^0.3.1",
33
33
  "@types/chai": "^4.3.4",
34
34
  "@types/chai-as-promised": "^7.1.5",
35
35
  "@types/chai-string": "^1.4.2",
@@ -65,16 +65,16 @@
65
65
  "typescript": "~4.9.4"
66
66
  },
67
67
  "peerDependencies": {
68
- "@sitecore-cloudsdk/events": "^0.3.0",
69
- "@sitecore-cloudsdk/personalize": "^0.3.0",
68
+ "@sitecore-cloudsdk/events": "^0.3.1",
69
+ "@sitecore-cloudsdk/personalize": "^0.3.1",
70
70
  "next": "^14.1.0",
71
71
  "react": "^18.2.0",
72
72
  "react-dom": "^18.2.0"
73
73
  },
74
74
  "dependencies": {
75
- "@sitecore-jss/sitecore-jss": "^22.1.0-canary.58",
76
- "@sitecore-jss/sitecore-jss-dev-tools": "^22.1.0-canary.58",
77
- "@sitecore-jss/sitecore-jss-react": "^22.1.0-canary.58",
75
+ "@sitecore-jss/sitecore-jss": "^22.1.0-canary.59",
76
+ "@sitecore-jss/sitecore-jss-dev-tools": "^22.1.0-canary.59",
77
+ "@sitecore-jss/sitecore-jss-react": "^22.1.0-canary.59",
78
78
  "@vercel/kv": "^0.2.1",
79
79
  "prop-types": "^15.8.1",
80
80
  "regex-parser": "^2.2.11",
@@ -82,7 +82,7 @@
82
82
  },
83
83
  "description": "",
84
84
  "types": "types/index.d.ts",
85
- "gitHead": "855f04c4ed8ac931b3ee4b67bdfd76e80fc277c5",
85
+ "gitHead": "61064aa0da07225a2929d7894ca05cd3b58a508b",
86
86
  "files": [
87
87
  "dist",
88
88
  "types",
@@ -37,6 +37,12 @@ export declare abstract class MiddlewareBase {
37
37
  * @returns {boolean} is preview
38
38
  */
39
39
  protected isPreview(req: NextRequest): boolean;
40
+ /**
41
+ * Determines if the request is a Next.js (next/link) prefetch request
42
+ * @param {NextRequest} req request
43
+ * @returns {boolean} is prefetch
44
+ */
45
+ protected isPrefetch(req: NextRequest): boolean;
40
46
  protected excludeRoute(pathname: string): boolean | undefined;
41
47
  /**
42
48
  * Safely extract all headers for debug logging
@@ -33,6 +33,10 @@ export type PersonalizeMiddlewareConfig = MiddlewareBaseConfig & {
33
33
  * Configuration for your Sitecore CDP endpoint
34
34
  */
35
35
  cdpConfig: CdpServiceConfig;
36
+ /**
37
+ * Optional Sitecore Personalize scope identifier allowing you to isolate your personalization data between XM Cloud environments
38
+ */
39
+ scope?: string;
36
40
  };
37
41
  /**
38
42
  * Object model of Experience Context data
@@ -47,6 +51,13 @@ export type ExperienceParams = {
47
51
  content: string | undefined;
48
52
  };
49
53
  };
54
+ /**
55
+ * Object model of personalize execution data
56
+ */
57
+ type PersonalizeExecution = {
58
+ friendlyId: string;
59
+ variantIds: string[];
60
+ };
50
61
  /**
51
62
  * Middleware / handler to support Sitecore Personalize
52
63
  */
@@ -68,15 +79,24 @@ export declare class PersonalizeMiddleware extends MiddlewareBase {
68
79
  request: NextRequest;
69
80
  response: NextResponse;
70
81
  }): Promise<void>;
71
- protected personalize({ params, personalizeInfo, language, timeout, }: {
72
- personalizeInfo: PersonalizeInfo;
82
+ protected personalize({ params, friendlyId, language, timeout, variantIds, }: {
73
83
  params: ExperienceParams;
84
+ friendlyId: string;
74
85
  language: string;
75
86
  timeout?: number;
87
+ variantIds?: string[];
76
88
  }, request: NextRequest): Promise<{
77
89
  variantId: string;
78
90
  }>;
79
91
  protected getExperienceParams(req: NextRequest): ExperienceParams;
80
92
  protected excludeRoute(pathname: string): boolean | undefined;
93
+ /**
94
+ * Aggregates personalize executions based on the provided route personalize information and language
95
+ * @param {PersonalizeInfo} personalizeInfo the route personalize information
96
+ * @param {string} language the language
97
+ * @returns An array of personalize executions
98
+ */
99
+ protected getPersonalizeExecutions(personalizeInfo: PersonalizeInfo, language: string): PersonalizeExecution[];
81
100
  private handler;
82
101
  }
102
+ export {};
@@ -67,8 +67,9 @@ export type RouteListQueryResult = {
67
67
  */
68
68
  export interface BaseGraphQLSitemapServiceConfig extends Omit<SiteRouteQueryVariables, 'language' | 'siteName'> {
69
69
  /**
70
- * A flag for whether to include personalized routes in service output - only works on XM Cloud
71
- * turned off by default
70
+ * A flag for whether to include personalized routes in service output.
71
+ * Only works on XM Cloud for pages using Embedded Personalization (not Component A/B testing).
72
+ * Turned off by default.
72
73
  */
73
74
  includePersonalizedRoutes?: boolean;
74
75
  /**