Using Google Tag Manager DataLayer with Uniform Signals

Last updated: February 4, 2026

Overview

Uniform Signals can leverage Google Tag Manager (GTM) dataLayer events to create powerful, event-driven personalization experiences. While Uniform uses its own event tracking system, you can bridge GTM events to Uniform with a straightforward one-time integration.

How It Works

Uniform Signals are based on Uniform's tracking events, not directly on GTM dataLayer events. However, you can forward all GA events to Uniform's tracker, enabling you to create signals based on any current or future GTM event.

GTM events exist in the dataLayer within the same page where they are added. Refreshing the page or navigating refreshes the dataLayer. When you push events into Uniform and trigger signals, you can define the persistency of the signals, meaning GTM events triggered on one page may be configured to affect Uniform personalization on another page.

Limitations

  • Uniform events are simple text values; you cannot add complex structures like arrays of purchased products with prices

  • The GA events → Uniform transformation needs to be configured in code and/or Google Tag Manager

  • Uniform personalization rules use only string-based conditions (equals, contains, etc.)

Why isn't this automatic? Google Analytics events may have any kind of structure, and Uniform events are simple text values. The transformation needs to be project-specific.

Implementation

The approach uses a Google Tag Manager custom event with a trigger for all events to produce a custom HTML tag. The tag code triggers a JavaScript event with the GA event payload, which is picked up by the Uniform context code in React to push the event into Uniform.

This approach was selected because:

  • Google Analytics or GTM doesn't provide a way to subscribe when dataLayer.push or gtag calls occur

  • Google discourages overriding or modifying the dataLayer logic

  • Uniform context.update call can only be added into a client-side React code

Example GA event structure:

In this example we used GA event like this: { event_label: 'purchase-successful', value: 100, } You can read any event, as long as appropriate tranformation is added. We only read the event_label to be used as event name in Uniform.

Step 1: Create a GTM User-Defined Variable

In your Google Tag Manager container:

  1. Navigate to Variables in the left sidebar

  2. Click New under User-Defined Variables

  3. Configure the variable:

    • Name: dlv - event_label

    • Variable Type: Data Layer Variable

    • Data Layer Variable Name: event_label

  4. Save the variable

Step 2: Add a Custom Event Trigger in GTM

Create a Custom Event trigger for all events:

  1. Navigate to Triggers in GTM

  2. Click New and select Custom Event as the trigger type

  3. Configure the trigger:

    • Event name: .* (RegEx Match)

    • This trigger fires on: All Custom Events

  4. Save the trigger

Now create a Custom HTML tag:

  1. Navigate to Tags and click New

  2. Select Custom HTML as the tag type

  3. Add this code:

<script>
(function () {
  window.dispatchEvent(
    new CustomEvent("gtm-event-triggered", {
      detail: { event: '{{dlv - event_label}}' }
    })
  )
})();
</script>
  1. Set the Triggering to the custom event trigger you created

  2. Save and Submit your GTM container changes

Step 3: Create a Next.js Client-Side Component

Create a new file at src/components/GaEventsTrigger.tsx:

'use client';

import { useEffect } from 'react';
import { useUniformContext } from '@uniformdev/canvas-next-rsc/component';

type GtmEventDetail = {
  event?: string;
};

export default function GaEventsTrigger() {
  const { context } = useUniformContext();

  useEffect(() => {
    const handler = (e: CustomEvent<GtmEventDetail>) => {
      const detail = e.detail;

      if (detail?.event) {
        context
          ?.update({
            events: [{ event: detail?.event }],
          })
          .then(() => {
            console.log('GA event sent', detail?.event);
          })
          .catch(err => {
            console.error('Failed to send GA event', err);
          });
      }
    };

    window.addEventListener('gtm-event-triggered', handler as EventListener);

    return () => {
      window.removeEventListener('gtm-event-triggered', handler as EventListener);
    };
  }, [context]);

  return null;
}

The useEffect dependency array includes Uniform context. This is crucial, because Uniform context is initialized slightly later after the page load.

Step 4: Add Component to Your Layout

Update your src/app/layout.tsx to include the new component:

import { UniformContext } from '@uniformdev/canvas-next-rsc';
import GaEventsTrigger from '@/components/GaEventsTrigger';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <UniformContext>
          <GaEventsTrigger />
          {children}
        </UniformContext>
      </body>
    </html>
  );
}

The component renders nothing visually but listens for GTM events in the background.

Step 5: Create Uniform Signals

After implementation, you can create Uniform signals with conditions based on the events:

  1. Navigate to Optimization > Signals in Uniform

  2. Create a new signal based on the events forwarded from GTM

  3. Set conditions using the event values (e.g., event equals "purchase-successful")

  4. Publish your manifest

Verification

To confirm the integration is working:

1. Test Event Forwarding

  1. Open your website in a browser

  2. Open browser DevTools (F12) and go to the Console tab

  3. Trigger a GTM event (e.g., click a button that fires a GTM event)

  4. Look for console logs showing "GA event sent" with the event name

  5. If you see the log, events are successfully forwarding to Uniform

2. Verify in GTM Preview Mode

  1. In GTM, click Preview to enter preview mode

  2. Visit your website

  3. Trigger an event

  4. In GTM Preview, verify:

    • The custom event trigger fires

    • The custom HTML tag executes

    • The dataLayer variable is populated

3. Check Uniform Context

  1. Install the Uniform Context browser extension

  2. Open your website and trigger a GTM event

  3. Open the Uniform Context extension

  4. Verify the event appears in the context data

4. Test Signal Activation

  1. Create a test signal in Uniform based on your GTM event

  2. Add personalization to a component using this signal

  3. Trigger the GTM event on your site

  4. Verify the personalization activates

Troubleshooting

Events Not Appearing in Uniform

Problem: GTM events fire but don't show up in Uniform signals

Solutions:

  • Verify the GTM event appears in GTM Preview and GA reports

  • Confirm your G-XXXX and GTM-YYYY codes are correct

  • Check browser console for errors in the GaEventsTrigger component

  • Ensure the Uniform Context is properly initialized before events fire

Custom HTML Tag Not Executing

Problem: The GTM custom HTML tag doesn't fire

Solutions:

  • Add console.log('GTM tag fired') to the custom HTML to verify execution

  • Check the trigger configuration matches all custom events (.* regex)

  • Ensure the tag is published in GTM (not just saved)

  • Verify the GTM container is loaded on your page

Signals Not Triggering Personalization

Problem: Events reach Uniform but personalization doesn't activate

Solutions:

  • Ensure Uniform signals are published (not just saved as drafts)

  • Verify signal conditions match the exact event values

  • Check signal persistence settings if testing across page navigations

  • Use the Uniform Context browser extension to force signal overrides for testing

Console Errors About Missing Context

Problem: "Cannot read property 'update' of undefined" errors

Solutions:

  • Verify GaEventsTrigger is placed inside <UniformContext>

  • Check that the Uniform Context provider is properly configured

  • Ensure environment variables for Uniform are set correctly

Additional Resources


Last Updated: January 28, 2026