diff --git a/CHANGELOG.md b/CHANGELOG.md index f1d2295d8d..375555febc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ Our versioning strategy is as follows: * `import { editingDataService } from '@sitecore-jss/sitecore-jss-nextjs/editing';` * `import { EditingRenderMiddleware } from '@sitecore-jss/sitecore-jss-nextjs/editing';` +* `[sitecore-jss-nextjs] [templates/nextjs-personalize]` getPointOfSale function passed into personalize middleware now accepts two parameters: site and language. Personalize middleware will use a built-in resolver if no function is passed. + * `[sitecore-jss-angular][templates/angular]` jss-angular package and sample has been updated to version 14. This means several changes: * JSS Angular sample is now using Ivy * IE11 no longer supported by JSS Angular diff --git a/packages/create-sitecore-jss/src/templates/nextjs-personalize/src/components/CdpPageView.tsx b/packages/create-sitecore-jss/src/templates/nextjs-personalize/src/components/CdpPageView.tsx index 30b66012c6..33d73bc2f4 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs-personalize/src/components/CdpPageView.tsx +++ b/packages/create-sitecore-jss/src/templates/nextjs-personalize/src/components/CdpPageView.tsx @@ -3,6 +3,7 @@ import { LayoutServicePageState, SiteInfo, useSitecoreContext, + PosResolver } from '@sitecore-jss/sitecore-jss-nextjs'; import { useEffect } from 'react'; import config from 'temp/config'; @@ -29,9 +30,7 @@ const CdpPageView = (): JSX.Element => { site: SiteInfo, pageVariantId: string ) => { - const pointOfSale = site.pointOfSale - ? site.pointOfSale[language] || site.pointOfSale[site.language] - : ''; + 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 || '', diff --git a/packages/create-sitecore-jss/src/templates/nextjs-personalize/src/lib/middleware/plugins/personalize.ts b/packages/create-sitecore-jss/src/templates/nextjs-personalize/src/lib/middleware/plugins/personalize.ts index b2e80fc226..dfc79e8ea4 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs-personalize/src/lib/middleware/plugins/personalize.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs-personalize/src/lib/middleware/plugins/personalize.ts @@ -50,6 +50,9 @@ 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/sitecore-jss-nextjs/src/index.ts b/packages/sitecore-jss-nextjs/src/index.ts index 245207956d..e8bc102357 100644 --- a/packages/sitecore-jss-nextjs/src/index.ts +++ b/packages/sitecore-jss-nextjs/src/index.ts @@ -65,6 +65,7 @@ export { getPersonalizedRewriteData, normalizePersonalizedRewrite, CdpHelper, + PosResolver, } from '@sitecore-jss/sitecore-jss/personalize'; export { GraphQLRequestClient } from '@sitecore-jss/sitecore-jss'; diff --git a/packages/sitecore-jss-nextjs/src/middleware/personalize-middleware.ts b/packages/sitecore-jss-nextjs/src/middleware/personalize-middleware.ts index 946f96d55c..74a06bb28e 100644 --- a/packages/sitecore-jss-nextjs/src/middleware/personalize-middleware.ts +++ b/packages/sitecore-jss-nextjs/src/middleware/personalize-middleware.ts @@ -7,8 +7,9 @@ import { ExperienceParams, getPersonalizedRewrite, } from '@sitecore-jss/sitecore-jss/personalize'; -import { SiteResolver } from '@sitecore-jss/sitecore-jss/site'; +import { SiteInfo, SiteResolver } from '@sitecore-jss/sitecore-jss/site'; import { debug, NativeDataFetcher } from '@sitecore-jss/sitecore-jss'; +import { PosResolver } from '@sitecore-jss/sitecore-jss/personalize'; export type PersonalizeMiddlewareConfig = { /** @@ -43,6 +44,13 @@ export type PersonalizeMiddlewareConfig = { * @default localhost */ defaultHostname?: string; + /** + * 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; }; /** @@ -235,9 +243,9 @@ export class PersonalizeMiddleware { // Execute targeted experience in CDP const { ua } = userAgent(req); const params = this.getExperienceParams(req); - const pointOfSale = site.pointOfSale - ? site.pointOfSale[language] || site.pointOfSale[site.language] - : ''; + const pointOfSale = this.config.getPointOfSale + ? this.config.getPointOfSale(site, language) + : PosResolver.resolve(site, language); const variantId = await this.cdpService.executeExperience( personalizeInfo.contentId, browserId, diff --git a/packages/sitecore-jss/src/personalize/index.ts b/packages/sitecore-jss/src/personalize/index.ts index 761bfb566a..013af4c214 100644 --- a/packages/sitecore-jss/src/personalize/index.ts +++ b/packages/sitecore-jss/src/personalize/index.ts @@ -1,4 +1,5 @@ export { personalizeLayout } from './layout-personalizer'; +export { PosResolver } from './pos-resolver'; export { GraphQLPersonalizeService, GraphQLPersonalizeServiceConfig, diff --git a/packages/sitecore-jss/src/personalize/pos-resolver.test.ts b/packages/sitecore-jss/src/personalize/pos-resolver.test.ts new file mode 100644 index 0000000000..798586f238 --- /dev/null +++ b/packages/sitecore-jss/src/personalize/pos-resolver.test.ts @@ -0,0 +1,77 @@ +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 return pos for site language as first 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'); + }); + + it('should use fallback value when other values missing', () => { + const site: SiteInfo = { + name: 'apos', + hostName: 'www.apos.com', + pointOfSale: { + 'de-DE': 'depos.com', + 'es-ES': 'espos.com', + '*': 'fallpos.com', + }, + language: 'en-CA', + }; + + const result = PosResolver.resolve(site, 'en'); + expect(result).to.equal('fallpos.com'); + }); +}); diff --git a/packages/sitecore-jss/src/personalize/pos-resolver.ts b/packages/sitecore-jss/src/personalize/pos-resolver.ts new file mode 100644 index 0000000000..4238aeb0ea --- /dev/null +++ b/packages/sitecore-jss/src/personalize/pos-resolver.ts @@ -0,0 +1,9 @@ +import { SiteInfo } from '../site'; + +export class PosResolver { + static resolve = (site: SiteInfo, language: string) => { + return site.pointOfSale + ? site.pointOfSale[language] || site.pointOfSale[site.language] || site.pointOfSale['*'] + : ''; + }; +}