npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jwiedeman/gtm-kit-react-legacy

v1.1.5

Published

Legacy React HOC adapter for GTM Kit - Google Tag Manager integration. For class components, supports React 16+.

Readme

@jwiedeman/gtm-kit-react-legacy

CI Coverage npm version Bundle Size TypeScript License: MIT React

React Higher-Order Component (HOC) for Google Tag Manager. For class components and pre-hooks React.

The legacy React adapter for GTM Kit - uses HOC pattern for class component compatibility.


Installation

npm install @jwiedeman/gtm-kit @jwiedeman/gtm-kit-react-legacy
yarn add @jwiedeman/gtm-kit @jwiedeman/gtm-kit-react-legacy
pnpm add @jwiedeman/gtm-kit @jwiedeman/gtm-kit-react-legacy

When to Use This Package

Use @jwiedeman/gtm-kit-react-legacy if:

  • You're using class components
  • Your project uses React < 16.8 (no hooks)
  • You prefer the HOC pattern
  • You're maintaining a legacy codebase

For new projects, we recommend @jwiedeman/gtm-kit-react which uses hooks.


Quick Start

Step 1: Wrap Your Root Component

import React from 'react';
import { withGtm } from '@jwiedeman/gtm-kit-react-legacy';

class App extends React.Component {
  render() {
    return <YourApp />;
  }
}

// Wrap with GTM - note the curried function pattern
export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(App);

Step 2: Use the GTM API in Child Components

The withGtm HOC injects a gtm prop with the full GTM API:

import React from 'react';
import { withGtm } from '@jwiedeman/gtm-kit-react-legacy';

class BuyButton extends React.Component {
  handleClick = () => {
    // Access push via the injected gtm prop
    this.props.gtm.push({ event: 'purchase', value: 49.99 });
  };

  render() {
    return <button onClick={this.handleClick}>Buy Now</button>;
  }
}

// Wrap any component to get the gtm prop
export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(BuyButton);

Features

| Feature | Description | | ------------------- | ------------------------------------ | | HOC Pattern | Works with class components | | React 16.0+ | Compatible with older React versions | | StrictMode-Safe | No double-fires in development mode | | TypeScript | Full type definitions included | | Consent Mode v2 | Built-in GDPR compliance support |


API Reference

withGtm(options)(Component)

A curried Higher-Order Component that wraps your component and provides GTM functionality.

import { withGtm } from '@jwiedeman/gtm-kit-react-legacy';

const WrappedComponent = withGtm({
  config: {
    containers: 'GTM-XXXXXX',
    dataLayerName: 'dataLayer' // optional
  },
  propName: 'gtm' // optional, defaults to 'gtm'
})(YourComponent);

Options

| Option | Type | Default | Description | | ---------- | ------------------------ | -------- | ------------------------- | | config | CreateGtmClientOptions | Required | GTM client configuration | | propName | string | 'gtm' | Name of the injected prop |

Injected Props

The wrapped component receives a prop (default name: gtm) with the following API:

interface LegacyGtmApi {
  client: GtmClient; // Raw GTM client
  push: (value: DataLayerValue) => void; // Push to dataLayer
  setConsentDefaults: (state, options?) => void; // Set consent defaults
  updateConsent: (state, options?) => void; // Update consent state
}

Usage Examples

Pushing Events

class TrackableButton extends React.Component {
  handleClick = () => {
    this.props.gtm.push({
      event: 'button_click',
      button_id: 'main-cta',
      button_text: 'Sign Up'
    });
  };

  render() {
    return <button onClick={this.handleClick}>Sign Up</button>;
  }
}

export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(TrackableButton);

E-commerce Tracking

class ProductCard extends React.Component {
  trackAddToCart = () => {
    this.props.gtm.push({
      event: 'add_to_cart',
      ecommerce: {
        items: [
          {
            item_id: this.props.product.id,
            item_name: this.props.product.name,
            price: this.props.product.price
          }
        ]
      }
    });
  };

  render() {
    return (
      <div>
        <h3>{this.props.product.name}</h3>
        <button onClick={this.trackAddToCart}>Add to Cart</button>
      </div>
    );
  }
}

export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(ProductCard);

Managing Consent

class CookieBanner extends React.Component {
  acceptAll = () => {
    this.props.gtm.updateConsent({
      ad_storage: 'granted',
      analytics_storage: 'granted',
      ad_user_data: 'granted',
      ad_personalization: 'granted'
    });
  };

  acceptAnalyticsOnly = () => {
    this.props.gtm.updateConsent({
      analytics_storage: 'granted'
    });
  };

  render() {
    return (
      <div className="cookie-banner">
        <p>We use cookies to improve your experience.</p>
        <button onClick={this.acceptAnalyticsOnly}>Analytics Only</button>
        <button onClick={this.acceptAll}>Accept All</button>
      </div>
    );
  }
}

export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(CookieBanner);

Setting Consent Defaults

class App extends React.Component {
  componentDidMount() {
    // Set consent defaults for EEA users
    this.props.gtm.setConsentDefaults(
      {
        ad_storage: 'denied',
        analytics_storage: 'denied',
        ad_user_data: 'denied',
        ad_personalization: 'denied'
      },
      { region: ['EEA'] }
    );
  }

  render() {
    return <YourApp />;
  }
}

export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(App);

Custom Prop Name

// Use a custom prop name instead of 'gtm'
class MyComponent extends React.Component {
  handleClick = () => {
    this.props.analytics.push({ event: 'click' });
  };

  render() {
    return <button onClick={this.handleClick}>Click</button>;
  }
}

export default withGtm({
  config: { containers: 'GTM-XXXXXX' },
  propName: 'analytics'
})(MyComponent);

Accessing the Raw Client

class AdvancedComponent extends React.Component {
  componentDidMount() {
    // Wait for GTM to be fully loaded
    this.props.gtm.client.whenReady().then(() => {
      console.log('GTM is ready!');
    });
  }

  render() {
    return <div>Advanced GTM usage</div>;
  }
}

export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(AdvancedComponent);

TypeScript Support

Full TypeScript definitions are included:

import React from 'react';
import { withGtm, LegacyGtmProps } from '@jwiedeman/gtm-kit-react-legacy';

interface MyComponentProps extends LegacyGtmProps {
  title: string;
}

class MyComponent extends React.Component<MyComponentProps> {
  handleClick = () => {
    // TypeScript knows gtm.push exists
    this.props.gtm.push({ event: 'click' });
  };

  render() {
    return <h1 onClick={this.handleClick}>{this.props.title}</h1>;
  }
}

export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(MyComponent);

Migrating to react-modern

If you're upgrading your codebase to use hooks, migration is straightforward:

// Before (react-legacy)
import { withGtm } from '@jwiedeman/gtm-kit-react-legacy';

class Button extends React.Component {
  render() {
    return <button onClick={() => this.props.gtm.push({ event: 'click' })}>Click</button>;
  }
}
export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(Button);

// After (react-modern)
import { useGtmPush } from '@jwiedeman/gtm-kit-react';

function Button() {
  const push = useGtmPush();
  return <button onClick={() => push({ event: 'click' })}>Click</button>;
}

Requirements

  • React 16.0+
  • @jwiedeman/gtm-kit (peer dependency)

Related Packages


Support

Have a question, found a bug, or need help?

Open an issue on GitHub — we're actively maintaining this project and respond quickly.


License

MIT