Google Tag Manager on SAP Commerce Cloud | OpsBlu Docs

Google Tag Manager on SAP Commerce Cloud

Step-by-step Google Tag Manager installation and configuration guide for SAP Commerce Cloud (Hybris).

This guide covers implementing Google Tag Manager on SAP Commerce Cloud for both Spartacus and Accelerator storefronts.

Prerequisites

  1. Create a GTM Container

    • Sign in to tagmanager.google.com
    • Create a new container (Web)
    • Copy your Container ID (format: GTM-XXXXXXX)
  2. SAP Commerce Access

    • Backoffice admin access
    • Extension development environment

Spartacus Implementation

Step 1: Create GTM Module

src/app/gtm/gtm.module.ts

import { NgModule, APP_INITIALIZER } from '@angular/core';
import { GtmService } from './gtm.service';

export function initializeGtm(gtmService: GtmService) {
  return () => gtmService.initialize();
}

@NgModule({
  providers: [
    GtmService,
    {
      provide: APP_INITIALIZER,
      useFactory: initializeGtm,
      deps: [GtmService],
      multi: true
    }
  ]
})
export class GtmModule {}

Step 2: Create GTM Service

src/app/gtm/gtm.service.ts

import { Injectable, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { ConfigService } from '@spartacus/core';

declare global {
  interface Window {
    dataLayer: any[];
  }
}

@Injectable({ providedIn: 'root' })
export class GtmService {
  private containerId: string;

  constructor(
    @Inject(PLATFORM_ID) private platformId: Object,
    private configService: ConfigService
  ) {
    this.containerId = this.configService.get('gtm.containerId') || '';
  }

  initialize(): void {
    if (!isPlatformBrowser(this.platformId) || !this.containerId) {
      return;
    }

    // Initialize dataLayer
    window.dataLayer = window.dataLayer || [];

    // Load GTM script
    this.loadGtmScript();
    this.addGtmNoscript();
  }

  private loadGtmScript(): void {
    const script = document.createElement('script');
    script.innerHTML = `
      (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
      new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
      j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
      'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
      })(window,document,'script','dataLayer','${this.containerId}');
    `;
    document.head.insertBefore(script, document.head.firstChild);
  }

  private addGtmNoscript(): void {
    const noscript = document.createElement('noscript');
    const iframe = document.createElement('iframe');
    iframe.src = `https://www.googletagmanager.com/ns.html?id=${this.containerId}`;
    iframe.height = '0';
    iframe.width = '0';
    iframe.style.display = 'none';
    iframe.style.visibility = 'hidden';
    noscript.appendChild(iframe);
    document.body.insertBefore(noscript, document.body.firstChild);
  }

  push(data: any): void {
    if (isPlatformBrowser(this.platformId)) {
      window.dataLayer = window.dataLayer || [];
      window.dataLayer.push(data);
    }
  }
}

Step 3: Configure GTM Container ID

src/app/spartacus/spartacus-configuration.module.ts

import { provideConfig } from '@spartacus/core';

@NgModule({
  providers: [
    provideConfig({
      gtm: {
        containerId: 'GTM-XXXXXXX'
      }
    })
  ]
})
export class SpartacusConfigurationModule {}

Accelerator Implementation

Step 1: Create GTM Tag Library

myanalytics/web/webroot/WEB-INF/tags/analytics/gtm.tag

<%@ tag body-content="empty" %>
<%@ attribute name="containerId" required="true" type="java.lang.String" %>

<!-- Google Tag Manager -->
<script>
    (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
    new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
    j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
    'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
    })(window,document,'script','dataLayer','${containerId}');
</script>

myanalytics/web/webroot/WEB-INF/tags/analytics/gtmNoscript.tag

<%@ tag body-content="empty" %>
<%@ attribute name="containerId" required="true" type="java.lang.String" %>

<!-- Google Tag Manager (noscript) -->
<noscript>
    <iframe src="https://www.googletagmanager.com/ns.html?id=${containerId}"
            height="0" width="0" style="display:none;visibility:hidden">
    </iframe>
</noscript>

Step 2: Include in Layout Templates

In <head> section:

<%@ taglib prefix="analytics" tagdir="/WEB-INF/tags/analytics" %>

<analytics:gtm containerId="${gtmContainerId}"/>

After <body> opening tag:

<analytics:gtmNoscript containerId="${gtmContainerId}"/>

Step 3: Initialize Data Layer

myanalytics/web/webroot/WEB-INF/tags/analytics/dataLayerInit.tag

<%@ tag body-content="empty" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<script>
    window.dataLayer = window.dataLayer || [];

    dataLayer.push({
        'pageType': '${pageType}',
        'siteName': '${currentSite.name}',
        'siteLocale': '${currentLanguage.isocode}',
        'currency': '${currentCurrency.isocode}'
    });

    <c:if test="${not empty user}">
    dataLayer.push({
        'userLoggedIn': true,
        'userType': '${user.customerType}'
    });
    </c:if>
    <c:if test="${empty user}">
    dataLayer.push({
        'userLoggedIn': false,
        'userType': 'guest'
    });
    </c:if>
</script>

Data Layer Implementation

Spartacus Event Tracking

src/app/gtm/gtm-events.service.ts

import { Injectable } from '@angular/core';
import { EventService } from '@spartacus/core';
import { GtmService } from './gtm.service';

@Injectable({ providedIn: 'root' })
export class GtmEventsService {
  constructor(
    private eventService: EventService,
    private gtmService: GtmService
  ) {
    this.setupEventListeners();
  }

  private setupEventListeners(): void {
    // Product viewed
    this.eventService.get('ProductDetailsPageEvent').subscribe(event => {
      this.gtmService.push({
        event: 'view_item',
        ecommerce: {
          items: [{
            item_id: event.product.code,
            item_name: event.product.name,
            price: event.product.price?.value
          }]
        }
      });
    });

    // Add to cart
    this.eventService.get('CartAddEntrySuccessEvent').subscribe(event => {
      this.gtmService.push({
        event: 'add_to_cart',
        ecommerce: {
          items: [{
            item_id: event.entry.product.code,
            item_name: event.entry.product.name,
            price: event.entry.basePrice?.value,
            quantity: event.entry.quantity
          }]
        }
      });
    });

    // Purchase
    this.eventService.get('OrderPlacedEvent').subscribe(event => {
      this.gtmService.push({
        event: 'purchase',
        ecommerce: {
          transaction_id: event.order.code,
          value: event.order.totalPrice?.value,
          currency: event.order.totalPrice?.currencyIso,
          items: event.order.entries?.map(entry => ({
            item_id: entry.product?.code,
            item_name: entry.product?.name,
            price: entry.basePrice?.value,
            quantity: entry.quantity
          }))
        }
      });
    });
  }
}

Verification

GTM Preview Mode

  1. Open GTM and click Preview
  2. Enter your storefront URL
  3. Navigate through pages
  4. Verify tags fire correctly

Debug Console

// Verify GTM loaded
console.log(google_tag_manager);

// Verify dataLayer
console.log(dataLayer);

Content Security Policy

For SSR/Universal rendering, configure CSP:

// server.ts
app.use((req, res, next) => {
  res.setHeader(
    'Content-Security-Policy',
    "script-src 'self' 'unsafe-inline' https://www.googletagmanager.com; " +
    "img-src 'self' https://www.googletagmanager.com;"
  );
  next();
});

Next Steps