Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to use custom dataLayer variable #401

Merged
merged 8 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 29 additions & 14 deletions src/gtm-support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { DataLayerObject } from './data-layer-object';
import type { GtmIdContainer } from './gtm-container';
import type { GtmSupportOptions } from './options';
import type { LoadScriptOptions } from './utils';
import { hasScript, loadScript } from './utils';
import { getOrInitializeDataLayer, hasScript, loadScript } from './utils';

/**
* Object definition for a track event.
Expand Down Expand Up @@ -54,6 +54,7 @@ export class GtmSupport {
loadScript: true,
defer: false,
compatibility: false,
dataLayerName: 'dataLayer',
...options,
};

Expand Down Expand Up @@ -144,14 +145,19 @@ export class GtmSupport {
}

/**
* Returns the `window.dataLayer` array if the script is running in browser context and the plugin is enabled,
* Returns the `window[dataLayerName]` array if the script is running in browser context and the plugin is enabled,
* otherwise `false`.
*
* @returns The `window.dataLayer` if script is running in browser context and plugin is enabled, otherwise `false`.
* @returns The `window[dataLayerName]` if script is running in browser context and plugin is enabled, otherwise `false`.
*/
public dataLayer(): DataLayerObject[] | false {
if (this.isInBrowserContext() && this.options.enabled) {
return (window.dataLayer = window.dataLayer ?? []);
const dataLayer: DataLayerObject[] = getOrInitializeDataLayer(
window,
this.options.dataLayerName,
);

return dataLayer;
}
return false;
}
Expand Down Expand Up @@ -183,8 +189,11 @@ export class GtmSupport {
}

if (trigger) {
const dataLayer: DataLayerObject[] = (window.dataLayer =
window.dataLayer ?? []);
const dataLayer: DataLayerObject[] = getOrInitializeDataLayer(
window,
this.options.dataLayerName,
);

dataLayer.push({
...additionalEventData,
event: this.options.trackViewEventProperty ?? 'content-view',
Expand All @@ -203,7 +212,7 @@ export class GtmSupport {
* regardless of whether the plugin is enabled or the plugin is being executed in browser context.
*
* @param param0 Object that will be used for configuring the event object passed to GTM.
* @param param0.event `event`, default to `"interaction"` when pushed to `window.dataLayer`.
* @param param0.event `event`, default to `"interaction"` when pushed to `dataLayer`.
* @param param0.category Optional `category`, passed as `target`.
* @param param0.action Optional `action`, passed as `action`.
* @param param0.label Optional `label`, passed as `"target-properties"`.
Expand Down Expand Up @@ -236,8 +245,11 @@ export class GtmSupport {
}

if (trigger) {
const dataLayer: DataLayerObject[] = (window.dataLayer =
window.dataLayer ?? []);
const dataLayer: DataLayerObject[] = getOrInitializeDataLayer(
window,
this.options.dataLayerName,
);

dataLayer.push({
event: event ?? 'interaction',
target: category,
Expand All @@ -251,14 +263,14 @@ export class GtmSupport {
}

/**
* Track an event by pushing the custom data directly to the `window.dataLayer`.
* Track an event by pushing the custom data directly to the `dataLayer`.
*
* The event will only be send if the script runs in browser context and the plugin is enabled.
* The event will only be send if the script runs in browser context, dataLayer exists, and the plugin is enabled.
*
* If debug mode is enabled, a "Dispatching event" is logged,
* regardless of whether the plugin is enabled or the plugin is being executed in browser context.
*
* @param data Event data object that is pushed to the `window.dataLayer`.
* @param data Event data object that is pushed to the `dataLayer`.
*/
public push(data: DataLayerObject): void {
const trigger: boolean =
Expand All @@ -271,8 +283,11 @@ export class GtmSupport {
}

if (trigger) {
const dataLayer: DataLayerObject[] = (window.dataLayer =
window.dataLayer ?? []);
const dataLayer: DataLayerObject[] = getOrInitializeDataLayer(
window,
this.options.dataLayerName,
);

dataLayer.push(data);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { DataLayerObject } from './data-layer-object';
declare global {
interface Window {
/**
* `dataLayer` used by GTM.
* Default `dataLayer` used by GTM.
*
* @see [developers.google.com/tag-manager/devguide](https://developers.google.com/tag-manager/devguide)
*/
Expand Down
10 changes: 10 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,14 @@ export interface GtmSupportOptions {
* @default content-view
*/
trackViewEventProperty?: string;
/**
* The name of the dataLayer variable to push events.
*
* @see https://developers.google.com/tag-platform/tag-manager/datalayer#rename_the_data_layer
*
* @example dataLayerName: 'dataLayerDemo'
*
* @default 'dataLayer'
*/
Shinigami92 marked this conversation as resolved.
Show resolved Hide resolved
dataLayerName?: string;
}
45 changes: 43 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { DataLayerObject } from './data-layer-object';
import type { GtmQueryParams } from './gtm-container';
import type { GtmSupportOptions } from './options';

/**
* OnReadyOptions.
Expand Down Expand Up @@ -58,6 +60,40 @@ export interface LoadScriptOptions {
* @param options Object containing container `id` and `script` element.
*/
onReady?: (options: OnReadyOptions) => void;
/**
* The GTM dataLayer name.
*
* @see https://developers.google.com/tag-platform/tag-manager/datalayer#rename_the_data_layer
*
* @default 'dataLayer'
*/
Shinigami92 marked this conversation as resolved.
Show resolved Hide resolved
dataLayerName?: string;
}

/**
* Extended window object to type dynamic dataLayer name.
*/
export interface DynamicDataLayerWindow extends Window {
[key: string]: any;
}

/**
* Ensure that the dataLayer is defined.
*
* @param window The window object.
* @param key The dataLayer name.
*
* @returns The dataLayer object.
*/
export function getOrInitializeDataLayer(
window: DynamicDataLayerWindow,
key: GtmSupportOptions['dataLayerName'] = 'dataLayer',
): DataLayerObject[] {
if (!window[key]) {
window[key] = [];
}

return window[key] as DataLayerObject[];
}

/**
Expand All @@ -82,9 +118,13 @@ export function loadScript(

script.addEventListener('load', scriptLoadListener);

window.dataLayer = window.dataLayer ?? [];
const dataLayerName: string = config.dataLayerName ?? 'dataLayer';
const dataLayer: DataLayerObject[] = getOrInitializeDataLayer(
window,
dataLayerName,
);

window.dataLayer?.push({
dataLayer.push({
event: 'gtm.js',
'gtm.start': new Date().getTime(),
});
Expand All @@ -106,6 +146,7 @@ export function loadScript(

const queryString: URLSearchParams = new URLSearchParams({
id,
...(config.dataLayerName ? { l: config.dataLayerName } : {}),
...(config.queryParams ?? {}),
});

Expand Down
Loading
Loading