diff --git a/CHANGELOG.md b/CHANGELOG.md index 582ba0a68f..8d7d5e8214 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,7 +72,7 @@ Our versioning strategy is as follows: * `[template/node-xmcloud-proxy]` `[sitecore-jss-proxy]` Introduced /api/healthz endpoint ([#1928](https://github.com/Sitecore/jss/pull/1928)) * `[sitecore-jss]` `[sitecore-jss-angular]` Render field metdata chromes in editMode metadata - in edit mode metadata in Pages, angular package field directives will render wrapping `code` elements with field metadata required for editing; ([#1926](https://github.com/Sitecore/jss/pull/1926)) * `[angular-xmcloud]``[sitecore-jss-angular]` Analytics and CloudSDK integration - * `[angular-xmcloud]` Add CloudSDK initialization on client side ([#1952](https://github.com/Sitecore/jss/pull/1952))([#1957](https://github.com/Sitecore/jss/pull/1957)) + * `[angular-xmcloud]` Add CloudSDK initialization on client side ([#1952](https://github.com/Sitecore/jss/pull/1952))([#1957](https://github.com/Sitecore/jss/pull/1957))([#1961](https://github.com/Sitecore/jss/pull/1961)) * `[angular-xmcloud]``[sitecore-jss-angular]` Add CDP Page View component to Angular XM Cloud add-on ([#1957](https://github.com/Sitecore/jss/pull/1957)) diff --git a/docs/upgrades/unreleased.md b/docs/upgrades/unreleased.md index 1ba6496bf1..abe7d1452d 100644 --- a/docs/upgrades/unreleased.md +++ b/docs/upgrades/unreleased.md @@ -295,13 +295,28 @@ If you plan to use the Angular SDK with XMCloud, you will need to perform next s * In XMCloud client side event tracking is done via CloudSDK so you need to make sure that it is initialized before send any event. See the following example of a component that does that; note that it should be added to the scripts.component.html before any other scripts that uses it; for more details take a look at the OOTB cloud-sdk-init.component.ts: ```ts + import { take } from 'rxjs/operators'; import { CloudSDK } from '@sitecore-cloudsdk/core/browser'; import '@sitecore-cloudsdk/events/browser'; import { environment } from '../../../environments/environment'; import { isServer } from '@sitecore-jss/sitecore-jss-angular'; + import { JssContextService } from '../../jss-context.service'; + import { JssState } from '../../JssState'; ... ngOnInit(): void { if (!isServer() && environment.production) { + // to ensure that CloudSDK initialization logic runs only once in the browser, take only the first emitted value of state + this.jssContext.state.pipe(take(1)).subscribe((newState: JssState) => { + const { + route, + context: { pageState }, + } = newState.sitecore; + + // Do not initialize CloudSDK in editing or preview mode or if missing route data + if (pageState !== LayoutServicePageState.Normal || !route?.itemId) { + return; + } + CloudSDK({ siteName: environment.sitecoreSiteName, sitecoreEdgeUrl: environment.sitecoreEdgeUrl, @@ -311,6 +326,7 @@ If you plan to use the Angular SDK with XMCloud, you will need to perform next s }) .addEvents() .initialize(); + }); } } ``` diff --git a/packages/create-sitecore-jss/src/templates/angular-xmcloud/src/app/routing/scripts/cloud-sdk-init.component.ts b/packages/create-sitecore-jss/src/templates/angular-xmcloud/src/app/routing/scripts/cloud-sdk-init.component.ts index 9801861595..035d58f751 100644 --- a/packages/create-sitecore-jss/src/templates/angular-xmcloud/src/app/routing/scripts/cloud-sdk-init.component.ts +++ b/packages/create-sitecore-jss/src/templates/angular-xmcloud/src/app/routing/scripts/cloud-sdk-init.component.ts @@ -1,8 +1,11 @@ import { Component, OnInit } from '@angular/core'; +import { take } from 'rxjs/operators'; import { CloudSDK } from '@sitecore-cloudsdk/core/browser'; import '@sitecore-cloudsdk/events/browser'; +import { isServer, LayoutServicePageState } from '@sitecore-jss/sitecore-jss-angular'; import { environment } from '../../../environments/environment'; -import { isServer } from '@sitecore-jss/sitecore-jss-angular'; +import { JssContextService } from '../../jss-context.service'; +import { JssState } from '../../JssState'; /** * Component to init CloudSDK logic - to allow events throughout the site @@ -12,21 +15,34 @@ import { isServer } from '@sitecore-jss/sitecore-jss-angular'; template: '', }) export class CloudSdkInitComponent implements OnInit { - constructor() {} + constructor(private jssContext: JssContextService) {} ngOnInit(): void { if (!isServer() && environment.production) { - CloudSDK({ - siteName: environment.sitecoreSiteName, - sitecoreEdgeUrl: environment.sitecoreEdgeUrl, - sitecoreEdgeContextId: environment.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, - }) - .addEvents() - .initialize(); + // to ensure that CloudSDK initialization logic runs only once in the browser, take only the first emitted value of state + this.jssContext.state.pipe(take(1)).subscribe((newState: JssState) => { + const { + route, + context: { pageState }, + } = newState.sitecore; + + // Do not initialize CloudSDK in editing or preview mode or if missing route data + if (pageState !== LayoutServicePageState.Normal || !route?.itemId) { + return; + } + + CloudSDK({ + siteName: environment.sitecoreSiteName, + sitecoreEdgeUrl: environment.sitecoreEdgeUrl, + sitecoreEdgeContextId: environment.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, + }) + .addEvents() + .initialize(); + }); } } }