This guide covers implementing Google Tag Manager on SAP Commerce Cloud for both Spartacus and Accelerator storefronts.
Prerequisites
Create a GTM Container
- Sign in to tagmanager.google.com
- Create a new container (Web)
- Copy your Container ID (format:
GTM-XXXXXXX)
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
- Open GTM and click Preview
- Enter your storefront URL
- Navigate through pages
- 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();
});