> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://contentful.com/developers/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://contentful.com/developers/docs/_mcp/server.

# Google Tag Manager plugin

> Send relevant events downstream to your customer data platforms or analytics tools.

The Google Tag Manager plugin sends data to a Google Tag Manager (GTM) container already present on your client-side application when an `<Experience>` component remains in the viewport for a specified amount of time. This allows you to forward events representing impressions of experiments and personalizations to any tags you have configured in GTM, including any downstream analytics systems you have configured as tags.

## Set up the Google Tag Manager

> **Info**
>
> This guide assumes that you are already familiar with Google Tag Manager (GTM) and have set up a container in your front-end. For more information, see the [GTM documentation](https://developers.google.com/tag-platform/tag-manager).

To track personalized components or measure experiment results, Google Tag Manager (GTM) requires some data from the data layer. Your triggers can then be set up through the values contained in the data layer.

### Step 1: Set up Variables

Variables help you send certain information about the Experience that was seen forward via Google Tag Manager.

To set up variables for your website:

1. Go to the "Variables" section in your [Google Tag Manager](https://tagmanager.google.com/) and create a new User-Defined variable.
2. Give your variable a name (according to your variable base on the next steps).
3. Select a variable type. Your variable type should be the `data layer`.
4. After choosing a variable type, you need to enter a name for the data layer variable field.
5. Save your variable.

### Step 2: Create an event trigger

An event trigger can be fired every time an Experience was seen.

To set up a trigger for your content:

1. Go to the "Triggers" section in your [Google Tag Manager](https://tagmanager.google.com/) and create a new trigger.
2. Enter a relevant name.
3. Select a trigger type, and choose **Custom event**.
4. Use `nt_experience` as the event name value.
5. Click **Save** to save your trigger.

### Step 3: Set up a tag to forward your experience trigger

To create a tag:

1. Go to the "Tags" section in your Google Tag Manager and create a new Tag.
2. Choose your tag type depending on where you want to send your data. For example, if you would like to forward data to Google Analytics, choose "Google Analytics: GA4 Event".
3. Enter an event name and event parameters. Here, you can now use the variables that you have set up before.
4. As a trigger, use the event trigger that you have previously set up.
5. Save your tag.

> **Info**
>
> Ensure that the destinations configured within your tags can receive and report on the data being sent with each `nt_experience` event. For example, Google Analytics 4 requires that you [define custom dimensions](https://support.google.com/analytics/answer/2709828?hl=en#configuration\&zippy=%2Cin-this-article) before you can receive them.

Repeat step 3 several times if you would like to forward these events to more destinations.

#### Preview website

You can now preview your website using Google Tag Manager's [Preview Mode](https://support.google.com/tagmanager/answer/6107056?hl=en) to see that events are triggered correctly. The trigger and tag that you have set up should now fire every time the user sees an Experience.

## Install the Google Tag Manager

To set up Contentful Personalization to send events to Google Tag Manager, you need to install the GTM plugin.

#### npm

```bash
npm install @ninetailed/experience.js-plugin-google-tagmanager
```

#### yarn

```bash
yarn add @ninetailed/experience.js-plugin-google-tagmanager
```

Then, add the plugin to the instance:

#### React, Next.js

```typescript
import { NinetailedGoogleTagmanagerPlugin } from '@ninetailed/experience.js-plugin-google-tagmanager';
```

```jsx
<NinetailedProvider
  // ...
  plugins={[
    new NinetailedGoogleTagmanagerPlugin()
  ]}
  componentViewTrackingThreshold={2000} // (Optional prop) Number, default = 2000
>
  //...
</NinetailedProvider>
```

#### Gatsby

```javascript
plugins: [
    // ...
    {
        resolve: `@ninetailed/experience.js-gatsby`,
        options: {
            // ...
            componentViewTrackingThreshold: 2000, // (Optional prop) Number, default = 2000
            ninetailedPlugins: [
                {
                    resolve: `@ninetailed/experience.js-plugin-google-tagmanager`,
                    options: {}
                }    
            ]
        }
    }
]
```

#### JavaScript

```javascript
import { Ninetailed } from '@ninetailed/experience.js';
import { NinetailedGoogleTagmanagerPlugin } from '@ninetailed/experience.js-plugin-google-tagmanager';

export const ninetailed = new Ninetailed(
    { 
        clientId: // Your client ID 
        environment: // Your Ninetailed environment
    }, 
    { 
        plugins: [
            new NinetailedGoogleTagmanagerPlugin()
        ],
        
        // Specify an amount of time (ms) that a component must be present in the viewport to register a component view
        componentViewTrackingThreshold: 2000,
    }
);
```

## Timing configuration

The Google Tag Manager Plugin logs that an element has been seen only after the element has remained within the user's viewport for a specified amount of time (in milliseconds), determined by the value of the `componentViewTrackingThreshold` property on the instance (see code samples above). If the option is unspecified, the value defaults to `2000`.

## Default data layer properties

Events sent from this plugin are named `nt_experience`. They are sent with the following default properties:

| Parameter                    | Value Type | Value Description                          |
| ---------------------------- | ---------- | ------------------------------------------ |
| ninetailed\_experience       | String     | Experience ID of the experience            |
| ninetailed\_experience\_name | String     | Title of the experience entry from the CMS |
| ninetailed\_variant          | String     | "control", "variant 1", "variant 2", …     |
| ninetailed\_audience         | String     | CMS entry ID of the audience               |
| ninetailed\_component        | String     | CMS entry ID of the shown variant          |

## Custom event properties

You can also define your own variables to push to GTM's data layer on each event by passing in a configuration object when instantiating the plugin. To do so, define a config object with a `template` property whose value is an object consisting of key-value pairs, where the key is the name of the property you want to add to the GTM data layer and the value is a string of the desired variable value surrounded by double curly braces (`&#123;&#123; &#125;&#125;`).

### Available properties

| Property                   | Notes                                                                                             |
| -------------------------- | ------------------------------------------------------------------------------------------------- |
| experience.id              |                                                                                                   |
| experience.type            | `nt_experiment` or `nt_personalization`                                                           |
| experience.name            |                                                                                                   |
| experience.description     |                                                                                                   |
| audience.id                | `ALL_VISITORS` if not set                                                                         |
| audience.name              | `All Visitors` if not set                                                                         |
| audience.description       |                                                                                                   |
| selectedVariant            |                                                                                                   |
| selectedVariant.YOUR\_PROP | Specify any property key from the selected experience variant                                     |
| selectedVariantIndex       | 0, 1, 2, etc.                                                                                     |
| selectedVariantSelector    | "control", "variant 1", "variant 2", etc. This is a mapping of `selectedVariantIndex` from above. |

### Example custom use

This example shows passing the human-readable name of an audience to a custom data layer property titled `ninetailed_audience_name`. The default data layer properties are also pushed.

#### React, Next.js

```jsx
<NinetailedProvider
   // ...
    plugins={[
      new NinetailedGoogleTagmanagerPlugin({
        template: {
          ninetailed_audience_name: '&#123;&#123; audience.name &#125;&#125;',
        },
      })
     ]}
     componentViewTrackingThreshold={2000}
  >
   //...
 </NinetailedProvider>
```

#### Gatsby

```javascript
plugins: [
    // ...
    {
        resolve: `@ninetailed/experience.js-gatsby`,
        options: {
            // ...
            componentViewTrackingThreshold: 2000,
            ninetailedPlugins: [
                {
                    resolve: `@ninetailed/experience.js-plugin-google-tagmanager`,
                    options: {
                        template: {
                            ninetailed_audience_name: '&#123;&#123; audience.name &#125;&#125;',
                        }
                    }
                }    
            ]
        }
    }
]
```

#### JavaScript

```javascript
import { Ninetailed } from '@ninetailed/experience.js';
import { NinetailedGoogleTagmanagerPlugin } from '@ninetailed/experience.js-plugin-google-tagmanager';

export const ninetailed = new Ninetailed(
    { 
        clientId: // Your client ID 
        environment: // Your Ninetailed environment
    }, 
    { 
        plugins: [
            new NinetailedGoogleTagmanagerPlugin({
              template: {
                ninetailed_audience_name: '&#123;&#123; audience.name &#125;&#125;',
              },
            })
        ],
        
        // Specify an amount of time (ms) that a component must be present in the viewport to register a component view
        componentViewTrackingThreshold: 2000,
    }
);
```