1. Developer guides

Analytics customization

Version: 1.x

This topic covers how to replace the default analytics registration with your own implementation, and how to register additional plugins, options, or a custom adapter. For what plugins and adapters are and which ones the Angular integration registers by default, see Plugins and Adapters.

Overriding the default implementation

The default implementation is a dependency injection (DI) provider, so you replace it the same way you replace any Angular provider: register your own SITECORE_ANALYTICS provider after provideSitecoreAngular() in the providers array. This overrides the built-in implementation.

Implement the interface

Your implementation must satisfy SitecoreAnalyticsWrapper, exported from @sitecore-content-sdk/angular. Inside it, call initContentSdk with whichever plugins you need. The following example implements a custom browser analytics provider:

import { Injectable, inject } from '@angular/core';
import { initContentSdk } from '@sitecore-content-sdk/core';
import { analyticsBrowserAdapter, analyticsPlugin } from '@sitecore-content-sdk/analytics-core'; // you can also implement your own
import { personalizeBrowserAdapter, personalizeBrowserPlugin, personalize, PersonalizeData } from '@sitecore-content-sdk/personalize'; // you can also implement your own
import { event, eventsPlugin, form, identity, pageView } from '@sitecore-content-sdk/events'; // for plugins, implement additional ones or import them
import type { EventData, IdentityData, PageViewData } from '@sitecore-content-sdk/events';
import { SITECORE_CONFIG_TOKEN, type SitecoreAnalyticsWrapper } from '@sitecore-content-sdk/angular';

@Injectable()
export class CustomBrowserAnalytics implements SitecoreAnalyticsWrapper {
  private readonly config = inject(SITECORE_CONFIG_TOKEN);
  private initPromise?: Promise<void>;
  private init(): Promise<void> {
    this.initPromise ??= initContentSdk({
      config: {
        contextId: this.config?.api?.edge?.clientContextId ?? '',
        edgeUrl: this.config?.api?.edge?.edgeUrl,
        siteName: this.config?.defaultSite ?? '',
      },
      plugins: [
        analyticsPlugin({
          options: { enableCookie: true, cookieExpiryDays: 30 },
          adapter: analyticsBrowserAdapter(),
        }),
        personalizeBrowserPlugin({
            adapter: personalizeBrowserAdapter(),
        }),
        eventsPlugin(),
        
      ],
    });
    return this.initPromise;
  }
  
  async pageView(data: PageViewData): Promise<void> {
    await this.init();
    await pageView(data);
  }

  async event(data: EventData): Promise<void> {
    await this.init();
    await event(data);
  }

  async identity(data: IdentityData): Promise<void> {
    await this.init();
    await identity(data);
  }

  async personalize(personalizeData: PersonalizeData): Promise<void> {
    await this.init();
    await personalize(personalizeData);
  }

  async form(
    formId: string,
    interactionType: 'VIEWED' | 'SUBMITTED',
    componentInstanceId: string
  ): Promise<void> {
    await this.init();
    await form(formId, interactionType, componentInstanceId);
  }
}

Register it after provideSitecoreAngular()

The default Content SDK analytics provider uses a factory that injects a provider with server or browser plugins, depending on the environment. If you implement custom behavior per environment, use a factory too:

// src/app/app.config.ts
import { PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';

export const appConfig: ApplicationConfig = {
  providers: [
    provideSitecoreAngular({
      sitecoreConfig: scConfig,
      sitecoreClient: getClient(),
    }),
    // Overrides the analytics implementation registered above.
    { provide: SITECORE_ANALYTICS,useFactory: () =>
      isPlatformBrowser(inject(PLATFORM_ID))
        ? new CustomBrowserAnalytics()
        : new CustomServerAnalytics()
    },
  ],
};

Order matters. Registering your provider before provideSitecoreAngular() has no effect, because the SDK's own provider is registered afterwards and takes precedence.

You can also decide whether to use browser or server plugins inside the custom provider implementation itself. In that case, you don't need useFactory, and a single implementation can be injected in both environments.

Registering additional plugins and adapters

The plugins array you pass to initContentSdk is where you extend the runtime. Each plugin can carry its own adapter, so a plugin list with three plugins can carry three adapters — one per capability, each matched to the environment the code runs in.

The Content SDK ships two adapter families:

Adapter familyInterfaceProvidesImplementations
AnalyticsAnalyticsAdapterClient ID handling, bot detection, URL search paramsanalyticsBrowserAdapter(), analyticsServerAdapter(req, res)
PersonalizePersonalizeAdapterProfile ID handling, user agentpersonalizeBrowserAdapter(), personalizeServerAdapter(req, res)

Adding personalization in the browser

The following example adds personalizeBrowserPlugin() to the browser plugin list. It carries the personalize browser adapter, while the analytics plugin keeps its own:

// src/content-sdk/analytics/custom-analytics.ts
import { analyticsBrowserAdapter, analyticsPlugin } from '@sitecore-content-sdk/analytics-core';
import { eventsPlugin } from '@sitecore-content-sdk/events';
import {
  personalizeBrowserAdapter,
  personalizeBrowserPlugin,
} from '@sitecore-content-sdk/personalize';

await initContentSdk({
  config: { contextId, edgeUrl, siteName },
  plugins: [
    analyticsPlugin({
      options: { enableCookie: true, cookieDomain: normalizeCookieDomain(location.hostname) },
      adapter: analyticsBrowserAdapter(),
    }),
    eventsPlugin(),
    personalizeBrowserPlugin({
      adapter: personalizeBrowserAdapter(),
      options: {
        enablePersonalizeCookie: true,
        webPersonalization: { async: true, defer: false },
      },
    }),
  ],
});

webPersonalization loads the Sitecore web personalization script in the browser. Pass true to use the defaults, or an object to control the async, defer, and language attributes. This option only applies in the browser.

Package dependencies

@sitecore-content-sdk/analytics-core, @sitecore-content-sdk/events, and @sitecore-content-sdk/personalize are peer dependencies of @sitecore-content-sdk/angular, so they are already installed and importable. To call initContentSdk directly, add the core package to your application:

npm install @sitecore-content-sdk/core

Overriding plugins in the Express middleware

The bot tracking and personalization middleware run outside the Angular injector, so DI does not apply to them. Their plugin sets are fixed, but you can configure their behavior through options: matcher and skip on both, and personalizeService, getExtraUtmParams, extractGeoDataCb, and skipForBot on personalization. If you need a different plugin set on the server, write your own Express middleware that calls initContentSdk, and register it in place of the built-in one.

If you have suggestions for improving this article, let us know!